threadWithMalloc
никогда не отправляет адрес выделенного хранилища обратно вызывающей стороне или основному потоку. Он объявляется с параметром vector
, а затем присваивает значение vector
:
vector = malloc(sizeof(int) * N);
Все, что это делает, это изменяет значение параметра, которое является локальным для функции. Изменение параметра в функции не приводит к изменению аргумента, переданного в основной подпрограмме. Таким образом, в основной подпрограмме pointer_vector[1]
не изменяется.
Чтобы исправить это, давайте сначала исправим обычные объявления. pthread_create
принимает параметр типа void *(*)(void *)
, который является указателем на процедуру, принимающую параметр void *
и возвращающую результат void *
. Таким образом, подпрограммы потока должны быть объявлены как подпрограммы, принимающие параметр void *
и возвращающие результат void *
, такой как:
void *threadWithoutMalloc(void *parameter)
Теперь внутри процедуры threadWithoutMalloc
хочет int *
, а не void *
. Мы можем удовлетворить это с помощью задания:
int *vector = parameter;
Затем, когда мы создаем поток для threadWithoutMalloc
, мы можем сделать это без приведения указателя:
rc = pthread_create(&threads[0], NULL, threadWithoutMalloc, pointer_vector[0]);
Ваш компилятор должен был предупреждать вас о коде pthread_create
, который вы имели - приведение подпрограммы к void *
является плохим признаком (и его поведение не определено стандартом C), и в результате void *
также должен был быть преобразован компилятором в тип параметра void *(*)(void *)
, который также имеет поведение, не определенное стандартом C, и является нарушением ограничения. Если ваш компилятор не дал вам предупреждений об этом, вам следует включить больше предупреждений в вашем компиляторе.
Для threadWithoutMalloc
код выше передает ему int *
, что хорошо для чего-то, что просто получает int *
. Для threadWithMalloc
мы хотим предоставить нам int *
. Один из способов сделать это - передать ему указатель на int *
, который дает ему адрес пространства, где мы хотим, чтобы он хранил int *
. Для этого мы можем передать ему адрес pointer_vector[1]
:
rc = pthread_create(&threads[1], NULL, threadWithMalloc, &pointer_vector[1]);
Затем, это threadWithMalloc
, мы снова хотим исправить его объявление:
void *threadWithMalloc(void *parameter)
и присвоить параметр объекту нужного типа:
int **vector = parameter;
Тогда, поскольку vector
является указателем на то, где будет находиться int *
, а не на int *
, мы меняем vector
на *vector
в следующем коде:
(*vector) = malloc(sizeof(int) * N);
int i;
for (i = 0; i < N; i++)
{
(*vector)[i] = i + 1;
}
Другим способом предоставления int *
основному потоку будет возвращение его в качестве возвращаемого значения pthreadWithMalloc
. Я использовал метод параметров только для иллюстрации различных типов параметров.