[英]What happens when you call malloc on an existing variable?
如果变量在过去已经是malloc
,那么如果再次调用malloc
而不是realloc
什么? 它会导致内存泄漏吗?
我想知道,以便我可以在malloc
调用传递给函数的参数之前添加检查,以避免潜在的泄漏。
void memtest(char **foo)
{
if ( foo )
*foo = malloc(10); // Assuming *foo was already allocated in the past.
}
我应该总是做以下事吗?
void memtest(char **foo)
{
if ( foo ) {
if ( *foo ) {
free(*foo);
*foo = NULL;
}
*foo = malloc(10);
}
}
如果*foo
的指针包含指向先前分配的内存的唯一指针,那么您刚刚泄漏了之前存在的内存。 否则,它是完全无害的。
对malloc
的调用无关紧要。
如果出现问题,问题是分配。 你做x=42;
无论它有多重要, x
的先前值都消失了。 类似地,如果foo
是你必须拥有某个内存的唯一指针,如果你覆盖foo
,你将无法再访问该内存。
如果不指定要免费的内容,则无法free
拨打电话。 因此,如果你在失去唯一指针之前没有释放内存,那么你就无法释放它,这就是内存泄漏的定义。
没有“在变量上调用malloc
”这样的东西。
malloc
找到一些“free”内存,将其标记为“used”,并返回刚刚找到的内存开头的地址。 free
标记一些“使用”的记忆为“免费”。
当你跑步
*foo = malloc(10);
发生以下情况:
malloc
找到10个字节的可用内存。 malloc
标记使用的那10个字节。 malloc
返回刚刚找到的10个字节的起始地址。 foo
的值,这是一个地址,因为foo
是一个指针。 malloc
存储在foo
中存储的地址中。 malloc
不关心你的程序对它返回的地址做了什么。 它不关心你的程序是将它存储在一个简单的变量,一个数组,另一个malloc
ed空间,还是将它写入一个文件。 它甚至不关心你的程序是否忘记了地址,但是你应该关心,因为如果程序不知道它试图释放的内存的地址,你的程序将永远不能free
调用。
有了这些知识,你应该能够看到这段代码的作用:
char *bar;
bar = malloc(10);
bar = malloc(10);
free(bar);
花点时间弄清楚,然后阅读下面的内容:
bar
的变量。 它的类型是char*
。 malloc
。 malloc
找到10个空闲字节并将它们标记为已使用。 malloc
返回10个字节的起始地址。 bar
。 ( bar
现在包含前10个字节的地址) malloc
。 malloc
找到10个更多的空闲字节,并将它们标记为已使用。 malloc
返回10个字节的起始地址。 bar
。 ( bar
现在包含第二个10字节的地址) free
并将其传递给后10个字节的起始地址。 free
将第二个10字节标记为free。 这是内存泄漏。 永远不会释放前10个字节。 我可以告诉他们永远不会被释放,因为程序不知道他们在哪个地址。
但是这个节目怎么样?
char *bar;
char *baz;
bar = malloc(10);
baz = bar;
baz = malloc(10);
在这里,我将malloc
称为“on”一个已经保存了malloc
ed的地址的变量。 这是内存泄漏吗? 不是单独的。 程序可能仍然free
第一个内存块,其地址仍然存储在baz
。
但是,这肯定是内存泄漏:
void func()
{
char *bar;
char *baz;
bar = malloc(10);
baz = bar;
baz = malloc(10);
}
我甚至没有改变代码,但只是把它放在一个函数中,它现在是一个内存泄漏! Whaaaaaaaaa?
记住内存泄漏究竟是什么。 内存泄漏是指程序分配内存但从不释放内存。 您无法通过查看malloc
调用来判断程序是否释放了所有内存。
至于第二部分 - “我应该这样做吗?”
不 ,你不应该。
只有传递给你的函数的地址的旧值是一个malloc
ed指针, 并且调用者忘记free
它时,它才会起作用。
您的建议将破坏以下任何功能:
void func1()
{
char c;
char *ptr = &c;
memtest(&ptr); // Tries to free something that wasn't malloced!
// ... do something with ptr ...
}
void func2()
{
char *ptr;
memtest(&ptr); // Passes a garbage address to free!
// ... do something with ptr ...
}
void func3()
{
char *ptr1 = malloc(5)
char *ptr2 = ptr1;
memtest(&ptr1);
// ... do something with ptr1 and ptr2 ...
free(ptr1); // Frees memory that was already freed!
}
总之:标题中的问题没有意义。 检测内存泄漏并不像这样简单。 而你想要做的是一个坏主意。
它导致内存泄漏,因为先前分配的内存未被任何变量引用,并且您丢失了其地址。
没有具体的检查。 您可以在声明时将指针设置为NULL
,并在每次free
内存时将其设置为NULL
。 然后你可以在调用malloc
之前检查if (pointer == NULL)
。
使用realloc
可以避免内存泄漏问题,因为如果指针是空指针,则realloc
函数的行为类似于指定大小的malloc
函数。 但如果未将指针声明设置为NULL
则可能会导致问题。
即:
int *foo = NULL;
void bar( void )
{
foo = realloc(foo, 10*sizeof(int));
}
realloc的一个好或坏特征是它保留了你记忆的内容。
我应该总是做以下事吗?
void memtest(char **foo)
{
if ( *foo )
free(*foo);
*foo = malloc(10);
}
不,你不应该因为free
而没有将指针设置为NULL
并且如果你的指针仍然具有已经free
ed内存的值,那么程序就会出错。 我的意思是,如果你在代码中的某个地方free
指针而不重新分配它,这样的代码就容易出错。 并且您必须确保将指针声明为NULL
作为初始值。
在现有变量上调用
malloc
时会发生什么?
可能性很小:
malloc
成功分配了内存,则重新分配内存将导致内存泄漏。 malloc
调用的内存分配失败,那么就不会有内存泄漏。 我应该总是做以下事吗?
void memtest(char **foo) { if ( *foo ) free(*foo); *foo = malloc(10); }
是。 通过这种方式,您可以确保没有内存泄漏。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.