Using realloc to shrink the allocated memory
有关C语言中realloc函数的简单问题:
如果我使用realloc缩小指针所指向的内存块,那么"额外"的内存是否会被释放?还是需要以某种方式手动释放它?
例如,如果我做
1 2 3
| int *myPointer = malloc(100*sizeof(int));
myPointer = realloc(myPointer ,50*sizeof(int));
free(myPointer ); |
我会发生内存泄漏吗?
- 严格来讲,存在内存泄漏,因为您没有记录realloc的结果,因此可能无法释放它。但是正如R .. \\的回答所表明的那样,您可能对实现细节很幸运。
-
糟糕,您是对的。我已尝试纠正它。现在怎么样?
-
如果realloc失败,新代码仍会泄漏原始分配。我希望大多数实现都不会缩小一个块,但允许这样做。不管是增大还是缩小块,调用realloc的正确方法都是void *tmp = realloc(myPointer, 50*sizeof(int)); if (!tmp) { /* handle error somehow. myPointer still points to the old block, which is still allocated */ } myPointer = tmp;。
不,您不会发生内存泄漏。 realloc将简单标记其余的"可用",以供将来的malloc操作使用。
但是稍后您仍然必须free myPointer。顺便说一句,如果在realloc中使用0作为大小,则在某些实现上,它与free具有相同的效果。正如史蒂夫·杰索普(Steve Jessop)和R ..在评论中所说,您不应该依赖它。
- "如果在重新分配中使用0作为大小,则它将与free具有相同的效果。"-在您的实现中可能是正确的,但不能保证。如果realloc从0输入返回空指针,并且未将errno设置为ENOMEM,则释放了内存。但是就像malloc一样,允许realloc尝试返回可用大小为0的实际分配。该实施需要记录哪些内容(7.20.3 / 1)。
-
史蒂夫是正确的,并且这样做的实际结果是,您永远不要调用大小为0的realloc。处理所有可能的行为,存在不一致的实现以及C和POSIX人士似乎不同意什么是一致的,什么不依赖于与realloc(x,0)相关的任何东西,这是一个非常糟糕的主意。
-
@Steve Jessop,R.。谢谢您的澄清:-)我从不费心检查POSIX之外的东西,我不知道它是非C标准的。
-
@cnicutar:Posix还允许实际的0大小分配。我不知道R ..指的是什么,但是它在C标准的解释上一定有所不同,因为它不像Posix那样简单地限制允许的行为。
-
POSIX说"如果size为0且ptr不是空指针,则指向的对象被释放。" ISO C没有此要求,实际上,如果实现选择让malloc(0)返回a唯一指针而不是NULL,似乎与C要求矛盾。这一切都足以使我感到困惑,我认为应用程序甚至都不应该尝试处理它,而只是避免胡说八道...
-
这不是正确的答案,重新分配仍然会泄漏。请阅读Azphare
绝对没有内存泄漏,但是当您调用realloc减小大小时,至少会发生三件事:
该实现将分配的内存块拆分为新的请求长度,并在最后释放未使用的部分。
该实现以新的大小进行新的分配,将旧内容复制到新位置,并释放整个旧分配。
该实现完全不执行任何操作。
选项3将是一个相当糟糕的实现,但是完全合法;仍然没有"内存泄漏",因为如果您以后在其上调用free,则整个内容仍将被释放。
对于选项1和2,更好的选择很大程度上取决于您是否喜欢性能还是避免内存碎片。我相信大多数现实世界的实现都会倾向于选择方法1。
如果重新分配失败,新代码仍会泄漏原始分配。我希望大多数实现都不会缩小一个块,但是允许这样做。正确的调用realloc的方法,无论是增大还是缩小块,都是无效的* tmp = realloc(myPointer,50 * sizeof(int)); if(!tmp){/ *以某种方式处理错误。 myPointer仍指向仍分配的旧块* /} myPointer = tmp;。 – 48分钟前史蒂夫·杰索普(Steve Jessop)
嘿,对不起,我不知道如何回复您的评论。
我需要将tmp转换为myPointer的类型吗?在这种情况下,我是否需要写
在这种情况下,当我
免费(myPointer)
tmp指向的内存也将被释放,对吗?所以不需要做
以您提供代码的方式,是的,它可能会泄漏。 realloc的想法是它可以为您返回数据的新位置。就像您在问题中所做的一样,您丢失了realloc向您发送的指针。
1 2 3
| int *myPointer2 = realloc(myPointer ,50*sizeof(int));
assert(myPointer2 );
myPointer = myPointer2 ; |
我猜想realloc()的过程是,它首先释放先前的内存块,然后再分配(我的大学老师告诉我)。如果仍然如此,它将已经释放了额外的50个字节。如果100字节内存中有数据,则会分配给50个重新分配的字节内存,这可能会导致数据丢失。因此,不应有内存泄漏。