C语言 使用 realloc 缩小分配的内存

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7078019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:24:40  来源:igfitidea点击:

Using realloc to shrink the allocated memory

cmemory-managementrealloc

提问by Moshe Rosenschein

Simple question about the realloc function in C: If I use realloc to shrink the memory block that a pointer is pointing to, does the "extra" memory get freed? Or does it need to be freed manually somehow?

关于 C 中 realloc 函数的简单问题:如果我使用 realloc 缩小指针指向的内存块,“额外”内存是否会被释放?还是需要以某种方式手动释放它?

For example, if I do

例如,如果我这样做

int *myPointer = malloc(100*sizeof(int));
myPointer = realloc(myPointer,50*sizeof(int));
free(myPointer);

Will I have a memory leak?

我会出现内存泄漏吗?

采纳答案by cnicutar

No, you won't have a memory leak. reallocwill simply mark the rest "available" for future mallocoperations.

不,你不会有内存泄漏。realloc将简单地将其余的标记为“可用”以供将来malloc操作。

But you still have to freemyPointerlater on. As an aside, if you use 0as the size in realloc, it will have the same effect as freeon some implementations. As Steve Jessop and R.. said in the comments, you shouldn't rely on it.

但你以后还是得freemyPointer这么做。顺便说一句,如果您使用0中的大小realloc,它将具有与free某些实现相同的效果。正如 Steve Jessop 和 R.. 在评论中所说,你不应该依赖它。

回答by R.. GitHub STOP HELPING ICE

There is definitely not a memory leak, but any of at least 3 things could happen when you call reallocto reduce the size:

绝对没有内存泄漏,但是当您调用realloc以减小大小时,至少可能发生 3 种情况中的任何一种:

  1. The implementation splits the allocated memory block at the new requested length and frees the unused portion at the end.
  2. The implementation makes a new allocation with the new size, copies the old contents to the new location, and frees the entire old allocation.
  3. The implementation does nothing at all.
  1. 该实现以新请求的长度拆分已分配的内存块,并在最后释放未使用的部分。
  2. 该实现使用新大小进行新分配,将旧内容复制到新位置,并释放整个旧分配。
  3. 实现什么都不做。

Option 3 would be a rather bad implementation, but perfectly legal; there's still no "memory leak" because the whole thing will still be freed if you later call freeon it.

选项 3 将是一个相当糟糕的实现,但完全合法;仍然没有“内存泄漏”,因为如果你以后调用free它,整个事情仍然会被释放。

As for options 1 and 2, which is better depends a lot on whether you favor performance or avoiding memory fragmentation. I believe most real-world implementations will lean towards doing option 1.

至于选项 1 和选项 2,哪个更好取决于您是偏爱性能还是避免内存碎片。我相信大多数现实世界的实现都会倾向于选择 1。

回答by azphare

The new code still leaks the original allocation if the realloc fails. I expect most implementations won't ever fail to shrink a block, but it's allowed. The correct way to call realloc, whether growing or shrinking the block, is 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;. – Steve Jessop 48 mins ago

如果重新分配失败,新代码仍然会泄漏原始分配。我希望大多数实现都不会无法缩小块,但这是允许的。无论是增大还是缩小块,调用 realloc 的正确方法是 void *tmp = realloc(myPointer, 50*sizeof(int)); if (!tmp) { /* 以某种方式处理错误。myPointer 仍然指向旧块,它仍然被分配 */ } myPointer = tmp;。– 史蒂夫·杰索普 48 分钟前

Hey, I couldn't figure out how to reply to your comment, sorry.

嘿,我不知道如何回复你的评论,抱歉。

Do I need to cast tmp to the type of myPointer? In this case, do I need to write

我是否需要将 tmp 转换为 myPointer 的类型?在这种情况下,我是否需要写

myPointer = (int*)tmp

Also, in this case, when I do free(myPointer) The memory pointed at by tmp will be freed as well, right? So no need to do

另外,在这种情况下,当我执行 free(myPointer) 时,tmp 指向的内存也会被释放,对吗?所以没必要做

free(myPointer)
free(tmp)

回答by Jens Gustedt

In the way you have given your code, yes, it might have a leak. The idea of reallocis that it can return you a new location of your data. Like you do it in your question you lose that pointer that reallocsends you.

按照您提供代码的方式,是的,它可能存在泄漏。的想法realloc是它可以为您返回数据的新位置。就像您在问题中所做的那样,您会丢失realloc发送给您的指针。

int *myPointer2 = realloc(myPointer,50*sizeof(int));
assert(myPointer2); 
myPointer = myPointer2;