在C中,请查看此代码,
static char* test = NULL;
typedef struct
{
char* member1;
}TestStruct;
void testCode()
{
TestStruct ts;
test = malloc(10*sizeof(char));
//assign characters to each test 0 ~ 9 positions
ts.member1 = test;
// using ts, then can I free static pointer test using free()?
free(test);
}
1)这个免费代码是对的吗?
2)分配的内存测试指向在堆中,对吗?
3)测试是在.bss?
4)如果testCode()函数可以在线程中调用,测试就是一个,对吗?但每次线程调用testCode()时,测试都会被赋予新指针并使内存泄漏,对吗?那么,我可以使用此代码来避免它吗?
Mutex_Start
if(test == NULL)
test = malloc(10*sizeof(char));
Mutex_End
请帮帮我。
答案 0 :(得分:5)
这个免费代码是对的吗?
如果意图是分配10个字节的内存,那么指定指向该内存的指针,然后删除内存,那么它是正确的。
但是代码中的评论表明你有点困惑。 ts.member1 = test;
只会使另一个指针指向同一块数据。你没有复制任何东西。从您free(test)
开始,test
和ts.member1
都指向无效的内存。
分配的内存测试指向在堆中,对吗?
是
测试是在.bss?
是
如果可以在线程中调用testCode()函数,test是1,对吗?
每次调用该函数时,都会创建一个新的内存块。但同样的功能也free()
内存。当然,如果另一个线程在第一个线程到达free()
之前获得焦点,它将分配另一块内存。例如:
所以你有内存泄漏和运行时崩溃。
那么,我可以使用此代码来避免它吗?
对NULL的检查可防止第二个线程分配任何新内存。如果这是意图并且两个线程都应该访问相同的内存,那么它将防止上述错误。但实际内存也必须受到竞争条件的保护,代码变得复杂。执行此操作的正确方法可能是在本地分配所有内容,而不是通过文件范围指针。
答案 1 :(得分:3)
我想你错过的是
test = NULL;
之后
free(test);
并在免费提供同样的保护,就像在mallocing之前做的那样
答案 2 :(得分:1)
在所有线程完成之后,您可以随时在free
注册的函数中调用atexit
,以便在进程结束时运行。但这确实是一个小问题,因为无论如何,这个过程将最终释放所有分配的内存。
更重要的是创业公司。 Modern C,AKA C11,有线程和互斥,所以你可以使用它,但它还有另一个更合适的构造,这里是原子。
static char*_Atomic test = ATOMIC_VAR_INIT(0);
void testCode(void)
{
TestStruct ts;
while (!test) {
char* tmp = malloc(10*sizeof(char));
if (!atomic_compare_exchange(&test, tmp, 0))
free(tmp);
}
/* Do whatever you have to do, here */
...
}
如果您的平台不支持C11的这个方面,您可以通过P99在许多平台上模拟它。
答案 3 :(得分:0)
如果您希望多个线程在同一个内存上工作,您应该将malloc和free放入启动并加入线程的代码中。你也可以做一些引用计数:
static char* test = NULL;
static int refCount = 0;
void testCode()
{
TestStruct ts;
{
//mutex lock;
if (!refCount++)
test = malloc(10*sizeof(char));
}
//assign characters to each test 0 ~ 9 positions
ts.member1 = test;
{
//mutex lock;
if (!--refCount)
free(test);
}
}
如果全局指针是某种全局资源,并且线程不必并行处理它,那么你应该在整个函数周围放置一个互斥体,从malloc到free。如果你只保护malloc并单独释放,一个线程可以释放另一个线程正在处理的内存!