如果新大小更小,可以重新分配指针吗?
Posted
技术标签:
【中文标题】如果新大小更小,可以重新分配指针吗?【英文标题】:can realloc move pointer if new size smaller? 【发布时间】:2010-12-16 17:23:36 【问题描述】:我想知道 C 或 C++ 标准是否保证在以较小(非零)大小调用 realloc 时指针不会更改:
size_t n=1000;
T*ptr=(T*)malloc(n*sizeof(T));
//<--do something useful (that won't touch/reallocate ptr of course)
size_t n2=100;//or any value in [1,n-1]
T*ptr2=(T*)realloc(ptr,n2*sizeof(T));
//<-- are we guaranteed that ptr2==ptr ?
基本上,操作系统是否可以自行决定,既然我们释放了一个大内存块,他想利用所有重新分配来对内存进行碎片整理,并以某种方式移动 ptr2?
【问题讨论】:
【参考方案1】:http://opengroup.org/onlinepubs/007908775/xsh/realloc.html
在大小不等于 0 的情况下成功完成后,realloc() 返回一个指向(可能已移动的)分配空间的指针。
不,不保证
【讨论】:
在该页面的前面,它说“realloc() 函数将 ptr 指向的内存对象的大小更改为 size 指定的大小。对象的内容将保持不变,直到新旧大小中的较小者。如果内存对象的新大小需要移动对象,则释放对象先前实例化的空间。不排除运动,但相对不太可能。 是的,您仍然可以保证之前内存中的内容仍然存在,感谢您指出这一点【参考方案2】:不保证realloc
将返回相同的位置,句号。
【讨论】:
如果在某处明确说明,那就太好了。不说“X 一定会发生”与明确说明“X 不保证会发生”是不一样的。 @RoG 是的,确实如此。不指定保证意味着没有保证。 @klutt 我明白你的意思,但很高兴看到它在某处明确说明,例如在书中,如果不在文档中。从用户的角度来看,找不到保证意味着要么没有保证,要么他们看错了地方。 @RoG 如果标准中没有说明,那么您可以编写一个没有该保证的一致实现。因此,如果标准不要求它,您通常不能期望它从实现中获得。当然,您仍然可以编写具有此保证的实现,因为它不会违反标准。因此,请查看标准或文档中的特定实现。但这真的很简单,因为标准没有要求,所以一般情况下不存在保证。 @RoG 另外,想要这样的证据有点像Russell's teapot。【参考方案3】:使用realloc
,您绝对无法保证后记的记忆位置。我相信 libc 的默认 malloc 只会不情愿地复制内存,所以实际上你可能没问题。但不要指望它。
【讨论】:
【参考方案4】:realloc
不需要将块留在原处,即使它适合,实际上最简单的存根实现就是一个示例,它可能不适合:
malloc
:拨打sbrk
。
realloc
:致电malloc
和memcpy
。
free
:无操作。
这听起来可能很荒谬,但有时对于嵌入式系统,我刚才描述的实现实际上是最佳实现。
【讨论】:
另一个例子是所有相邻分配都是相同大小的块以避免碎片的实现。在这种情况下,一个 32 字节的块不再属于与之前的 4096 字节块相同的位置。 是的。另一个更高级的例子是一个实现,它检查要收缩的块的左侧邻居是否空闲,是否会通过收缩在右侧创建一个重要的空闲块,结果大小是否“足够小” "memcpy
不会太贵...如果满足正确的条件,将块移动到新位置以避免碎片。【参考方案5】:
在我看来,所有当前的答案(在这个答案的时候)都没有参考任何标准文档。
对于 C++,我将参考Working Draft, Standard for Programming Language C++, Document Number: N3337, Date: 2012-01-16, Revises: N3291,根据https://isocpp.org/std/the-standard,它是最接近非免费官方 C++11 标准文档的免费文档;在这里我们可以在 20.6.13 C 库找到:
2 内容与标准 C 库头文件相同, 具有以下更改:[在我看来,列出的更改与 问题]。
所以现在我们必须参考 C 标准。
根据https://***.com/a/83763/15485,最接近非免费官方C11标准文档的免费文档是Programming languages — C, N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x;在这里我们发现 7.22.3.5 的 realloc 函数:
4 realloc 函数返回一个指向新对象的指针( 可能与指向旧对象的指针具有相同的值),或者为空 无法分配新对象时的指针。
我不是以英语为母语的人,所以由你来解释“可能有”的含义。
【讨论】:
我的母语是英语(并且非常熟悉 C 标准)。引用的文本说新指针可能与旧指针具有相同的值,也可能不同,但这并不意味着这取决于大小。一个基本原理(标准中没有说明)是一个实现可以在不同的位置分配一个较小的块,以减少碎片并使未来的分配更有可能成功。为了保证它在某些情况下不会移动,必须在标准中明确说明。不是。【参考方案6】:在 Windows 上,C-Runtime 抓取一个堆,然后从该堆分配内存。所以操作系统不会知道单个内存分配,因此不会移动。
【讨论】:
这是不正确的。一方面,Visual C 运行时不直接调用 OS 堆实现。另一方面,HeapReAlloc() 调用确实移动了一些东西。 您需要仔细检查您的文档。请参阅:msdn.microsoft.com/en-us/library/csd157zx.aspx CRT 抓取单个 OS 堆以供内部使用。然后它再分配该堆(这意味着它不使用 Win32 堆调用在该堆内进行分配)以上是关于如果新大小更小,可以重新分配指针吗?的主要内容,如果未能解决你的问题,请参考以下文章
如果我重新分配并且新大小为 0,会发生啥情况。这是不是等同于免费?
Gridster 与 Highcharts,使特定图表更小并重新计算