据我所知,malloc()
(或任何堆分配函数)和free()
必须配对。我认为在多线程程序中是相同的。但是看起来我不应该free()
分配给另一个线程的堆变量。
当我在wsl ubuntu环境中运行以下代码时,
#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);
msg = "thread end\n";
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); // if I comment out this line, the program succeeds.
return 0;
}
我得到标准输出
thread running... 0
thread running... 1
thread running... 2
thread running... 3
thread running... 4
thread returned message : thread end
munmap_chunk(): invalid pointer
Aborted (core dumped)
但是,如果我注释掉free(thread_return);
部分,程序将成功执行并且不会产生异常中止的错误转储消息。
那么,有没有必要释放从另一个线程创建的堆变量?甚至更多,如果它是从另一个线程创建的,则释放堆变量是否错误?
答案 0 :(得分:2)
char* msg = (char*)malloc(sizeof(char) * 50);
msg = "thread end\n";
此处的第二行用指向常量字符串的指针覆盖malloc()
分配的指针,从而导致最初分配的内存泄漏。该线程返回的值指向该常量字符串,而不是malloc()
分配的内存;尝试free()
的值将失败,因为malloc()
并未分配该值。
使用strncpy()
将字符串写入malloc()
分配的内存中。完成此操作后,您可以(并且应该)在主线程中用free()
释放结果内存。
答案 1 :(得分:-1)
简而言之
总是在分配它的同一逻辑单元中释放分配的内存。
理由
如果您释放在另一个线程上分配的内存,或者甚至说您决定将要动态释放的缓冲区作为函数的参数接收,而您决定将其释放,则会引起很多问题。
将来使用此变量可能会导致程序崩溃,因为它试图进入未分配的内存。
这确实是最佳实践,就像我在总结中所写的那样,尤其是在为具有多个开发人员的大型项目编写代码时-因为您始终无法知道动态分配的缓冲区的将来会发生什么。
崩溃
解决崩溃问题,不是由您试图释放分配给另一个线程的内存引起的,而是因为使用以下行而发生的:
msg = "thread end\n";
在分配内存并将其分配给msg之后,您丢失了指向已分配内存的指针。现在释放“ msg”时,您尝试释放分配在堆栈上的变量。