如何在主函数中释放由线程函数分配的内存

3

我在线程函数 f1 中分配了 heap 内存,这个内存用于计算堆区的值,以便主函数可以看到它。

以下是线程函数的定义:

void *f1(void *input){


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

在上面的代码中,sum 是动态分配的存储空间,其地址作为返回值传递给 main() 中的 sum1
我在 main() 中这样使用 join 函数来加入线程:
void *sum1;
pthread_join(tid1,(void**)&sum1);

我取回值后,希望free已分配的内存空间。但当我在主函数中使用free时,会出现munmap_chunk(): invalid pointer这样的错误提示。

我该怎么明确且安全地free这段内存空间呢?


2
你写了 int sum,我猜这里需要一个指针。 - prog-fh
@prog-fh。你说得对,这是一个打字错误,让我来纠正一下。 - Nouman Tajik
请不要修复那些对于提问来说是必要的代码漏洞。 - Antti Haapala -- Слава Україні
2个回答

3
你应该返回指针本身,而不是它的地址。
pthread_exit(sum);
...
pthread_join(tid1, &sum1);

在线程函数中,你想要通过return或者pthread_exit()发送一个指针。

然后,在pthread_join()中,你需要获取这个指针,但是pthread_join()的返回值是一个用于报告成功/失败的整数。

因此,我们需要声明一个指针变量(例如这里的sum1),用于存储预期的结果,并向pthread_join()提供该变量的地址,以便它可以被更新(就像我们向scanf()提供地址以更新提取的变量一样)。


3
你代码中的问题在于使用了强制类型转换。在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 *value内联转换为int *时:

int value = *(int *)sum1;

但是你也可以通过赋值来转换它,而且再次强调,不需要进行类型转换:

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

经验法则是,如果您知道比编译器更好的东西,例如“将此值截断为uint8_t”或“这个空指针实际上指向一个int,但我不想分配它来节省按键次数”,那么转换是可以的 - 但通常不能只是为了消除警告而进行转换。


一些程序员编写以下类似的代码:

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

这样的代码不是严格符合标准的,因为int *void *类型并不兼容,它们可能具有不同的表示形式或大小,尤其是它们可能不能相互引用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接