Как освободить память, выделенную поток-функцией в основной - PullRequest
3 голосов
/ 10 июля 2019

Я выделил heap память в функции потока f1, эта память используется для вычисления значения в области кучи, чтобы основная функция могла его увидеть.

Вот функция потокаопределение:

void *f1(void *input){


        int sum = (int*)malloc(sizeof(int));
        /* Do calculation */   
        pthread_exit((void*)&sum);
}

В вышеприведенном коде sum - это выделенная куча память, адрес которой передается как sum1 в main().

* 1012 как возвращаемое значение.* I join поток в main() выглядит следующим образом:
void *sum1;
pthread_join(tid1,(void**)&sum1);

После того как я получил значение, я хочу free выделенную память.Когда я использую free в основном, он жалуется как munmap_chunk(): invalid pointer

Как я могу явно и безопасно free эта память?

Ответы [ 2 ]

5 голосов
/ 10 июля 2019

Проблема в вашем коде - использование casts . В C большую часть времени приведение указателя означает ошибочную конструкцию . Примечательно, что в этом примере никакие приведения не требуются, если конструкции используются правильно:

// no cast required because malloc returns void * and void * can be converted
// to a pointer to int without a cast
int *sum = malloc(sizeof (int));

// no cast required because int * can be converted to a void * without a cast
pthread_exit(sum);

void *sum1;

// no cast required because the address of void * is a void **!
pthread_join(tid1, &sum1);

Единственное место, где вам требуется приведение, это если вы сейчас конвертируете это void * значение в int * inline:

int value = *(int *)sum1;

но вы также можете преобразовать его по заданию, и опять же, приведение не требуется:

int *value_ptr = sum1;
printf("The value was %d\n", *value_ptr);
free(value_ptr);

Эмпирическое правило заключается в том, что приведение в порядке, если вы знаете что-то лучше, чем компилятор - например, "усечь это значение до uint8_t" или "этот указатель void фактически указывает на int, но я не назначаю это для того, чтобы сохранить нажатия клавиш "- но обычно не нормально просто замолчать предупреждение.


Некоторые программисты пишут такой код:

int *ptr;
pthread_join(tid1, (void **)&ptr);

Такой код не является строго соответствующим, так как int * и void * не являются совместимыми типами, могут иметь или не иметь одинаковое представление или даже размер, и, в частности, могут не совмещать друг друга.

4 голосов
/ 10 июля 2019

Вы должны отправить обратно указатель, а не его адрес

pthread_exit(sum);
...
pthread_join(tid1, &sum1);

Из функции потока, которую вы хотите отправить обратно (с return или pthread_exit()) указатель.
В pthread_join() вы хотите получить этот указатель, но результатом pthread_join() является целое число, чтобы сообщить об успехе / неудаче.
Затем мы должны объявить переменную-указатель (sum1 здесь), чтобы сохранить ожидаемый результат и предоставить pthread_join()с адресом этой переменной, чтобы ее можно было обновить (так же, как мы предоставляем адреса scanf() для обновления извлеченных переменных).

...