В вашей программе две добросовестных ошибки. Первое, что я уже рассмотрел в комментариях: объявлена функция producer()
, возвращающая значение, но на самом деле это не так. В результате вызов этой функции приводит к неопределенному поведению. Поскольку вы на самом деле не используете возвращаемое значение, вы можете исправить это, просто сделав функцию, возвращающую NULL
.
Но, вероятно, более важно, что ваша main()
функция выделяет слишком мало места для thread_arg
:
thread_arg=(struct thread_args*)malloc(sizeof(struct thread_args*));
Вы выделяете пространство размером с указатель, но вам нужно достаточно места для struct thread_args
, который, безусловно, больше (в Ubuntu), поскольку он содержит четыре указателя. C не требует, чтобы указатели на разные типы объектов были одинакового размера, но в Linux они есть. Таким образом, правильное распределение будет
thread_arg = (struct thread_args*) malloc(sizeof(struct thread_args));
ОДНАКО, в C плохая форма для приведения результата malloc()
, язык не требует его, и это может маскировать ошибки, о которых ваш компилятор мог бы сообщать вам. (Это отличается в C ++.) Таким образом, это было бы лучше:
thread_arg = malloc(sizeof(struct thread_args));
То же самое относится ко всем присваиваниям, где одна сторона является указателем на void, а другая - указателем на любой тип объекта, а также на передачу аргументов функциям, не являющимся varargs.
Но мы можем сделать еще лучше. Обратите внимание, что из этого оператора не сразу ясно, какой тип thread_arg
, чтобы убедиться, что выделено правильное количество байтов. Также обратите внимание на то, что может произойти, если thread_arg
впоследствии будет изменен на другой тип, и исправление этого распределения было пропущено. Эти проблемы можно решить, установив размер с помощью выражения нужного типа, а не с помощью имени этого типа:
thread_arg = malloc(sizeof(*thread_arg));
Обратите внимание, что аргумент sizeof()
не оценивается (кроме случаев, когда его тип имеет переменную длину, что здесь не так), поэтому использование выражения *thread_arg
до присвоения значения не является проблемой до thread_arg
. И результирующее утверждение четко и однозначно верно. В английском это говорит: «выделите пространство размером с вещь, на которую указывает thread_arg
, и назначьте указатель на это пространство на thread_arg
».