线程分配的堆变量无需free?跨线程调用free()为何报错?
问题分析:你的错误不是跨线程释放,而是指针被覆盖了!
嘿,先别误会跨线程释放的问题,咱们先揪出你代码里的关键bug:
看你子线程里的这段代码:
char* msg = (char*)malloc(sizeof(char) * 50); msg = "thread end\n";
你先用malloc在堆上申请了一块内存,但是紧接着直接把msg的指针指向了字符串字面量"thread end\n"——这个字面量是存在进程的只读数据段里的,根本不是你刚malloc出来的堆内存!
这就导致你最后返回给主线程的thread_return,其实是一个只读常量的地址,而不是堆内存的地址。这时候你调用free(thread_return),相当于尝试释放只读数据段的内容,系统当然会报错munmap_chunk(): invalid pointer,因为free只能用来释放堆上的内存。
关于跨线程释放堆内存的说明
其实在POSIX标准(包括你用的WSL Ubuntu环境)中,跨线程释放堆内存是完全合法的操作!堆是进程级别的共享资源,所有线程共享同一个堆空间,只要你要释放的指针是合法的(由malloc/calloc/realloc分配的堆地址),不管这个指针是哪个线程分配的,都可以在任意线程里调用free来释放,完全没问题。
修正后的代码示例
把字符串复制到malloc的堆内存里,而不是直接赋值指针就可以解决问题:
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> void* thread_main(void* arg) { int i = 0; for (; i < *((int*)arg); i++) { printf("thread running... %d\n", i); } char* msg = (char*)malloc(sizeof(char) * 50); strcpy(msg, "thread end\n"); // 用strcpy把字符串复制到堆内存中 return (void*)msg; } int main() { pthread_t thread_id; int thread_arg = 5; void* thread_return; pthread_create(&thread_id, NULL, thread_main, (void*)&thread_arg); pthread_join(thread_id, &thread_return); printf("thread returned message : %s", (char*)thread_return); free(thread_return); // 现在可以正常释放了! return 0; }
这样修改后,主线程释放子线程分配的堆内存就不会报错了。
内容的提问来源于stack exchange,提问作者pitachips
相关产品推荐
相关产品推荐

