是否不需要 free() 从线程分配和返回的堆变量?
Is there no need to free() a heap variable allocated and returned from a thread?
据我所知,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);
部分,程序会成功并且不会产生中止错误转储消息。
那么,是否不需要释放从另一个线程创建的堆变量?甚至更多,如果它是从另一个线程创建的,那么释放堆变量是错误的吗?
简而言之
始终在分配它的同一逻辑单元中释放分配的内存。
推理
如果您释放在另一个线程上分配的内存,或者甚至说您接收到一个动态分配的缓冲区作为您的函数的参数,您决定释放它 - 您可能会导致很多问题。
以后使用此变量可能会导致您的程序崩溃,因为它试图获取未分配的内存。
按照我在摘要中写的那样做确实是最佳实践,尤其是在为具有多个开发人员的大型项目编写代码时 - 因为您无法始终知道动态分配的缓冲区未来会发生什么。
崩溃
解决您的崩溃,这不是您试图释放在另一个线程上分配的内存引起的 - 它只是发生在使用以下行时:
msg = "thread end\n";
在分配内存并将其分配给 msg 之后,您丢失了指向已分配内存的指针。现在,当释放 "msg" 时,您正在尝试释放分配在堆栈上的变量。
char* msg = (char*)malloc(sizeof(char) * 50);
msg = "thread end\n";
这里的第二行将malloc()
分配的指针覆盖为一个常量字符串的指针,导致原本分配的内存泄漏。这个线程返回的值指向那个常量字符串,而不是malloc()
分配的内存;尝试 free()
该值将失败,因为它不是由 malloc()
.
分配的
使用strncpy()
向malloc()
分配的内存中写入一个字符串。完成后,您可以(并且应该)在主线程中使用 free()
释放生成的内存。
据我所知,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);
部分,程序会成功并且不会产生中止错误转储消息。
那么,是否不需要释放从另一个线程创建的堆变量?甚至更多,如果它是从另一个线程创建的,那么释放堆变量是错误的吗?
简而言之
始终在分配它的同一逻辑单元中释放分配的内存。
推理
如果您释放在另一个线程上分配的内存,或者甚至说您接收到一个动态分配的缓冲区作为您的函数的参数,您决定释放它 - 您可能会导致很多问题。
以后使用此变量可能会导致您的程序崩溃,因为它试图获取未分配的内存。
按照我在摘要中写的那样做确实是最佳实践,尤其是在为具有多个开发人员的大型项目编写代码时 - 因为您无法始终知道动态分配的缓冲区未来会发生什么。
崩溃
解决您的崩溃,这不是您试图释放在另一个线程上分配的内存引起的 - 它只是发生在使用以下行时:
msg = "thread end\n";
在分配内存并将其分配给 msg 之后,您丢失了指向已分配内存的指针。现在,当释放 "msg" 时,您正在尝试释放分配在堆栈上的变量。
char* msg = (char*)malloc(sizeof(char) * 50);
msg = "thread end\n";
这里的第二行将malloc()
分配的指针覆盖为一个常量字符串的指针,导致原本分配的内存泄漏。这个线程返回的值指向那个常量字符串,而不是malloc()
分配的内存;尝试 free()
该值将失败,因为它不是由 malloc()
.
使用strncpy()
向malloc()
分配的内存中写入一个字符串。完成后,您可以(并且应该)在主线程中使用 free()
释放生成的内存。