S. *_*rma 4 c realloc dynamic-memory-allocation
的手册页中realloc()说:
该
realloc()函数将指向的存储块的大小更改ptr为size字节。从区域开始到新旧大小的最小值之间的内容将保持不变。如果新的大小大于旧的大小,则不会初始化添加的内存。
但是,手册页没有说明如果新大小小于旧大小会发生什么。例如,如果我有以下代码:
ptr = realloc(ptr, nsize); // Where nsize < the original size and ptr is of type void **
Run Code Online (Sandbox Code Playgroud)
如果原始大小为size,是否表示ptr + nsize + 1仍包含分配的条目?
任何帮助表示赞赏。
首先,您可能是说:
void **ptr = malloc(nsize*2);
Run Code Online (Sandbox Code Playgroud)
然后
ptr = realloc(ptr, nsize);
Run Code Online (Sandbox Code Playgroud)
还是安全的方法:
void **ptr2 = realloc(ptr, nsize);
if (ptr2 != NULL)
{
ptr = ptr2;
} // else failure
Run Code Online (Sandbox Code Playgroud)
因为realloc(ptr,nsize)用于设置的值ptr是未定义的行为,并且可能会崩溃。
现在,系统按照“减少内存大小”中的说明进行操作,是否可以假设以较小的大小调用realloc将释放剩余的空间?
现在您的问题是:
如果原始大小为
size,是否表示ptr + nsize + 1仍包含分配的条目?
您无法保证。这是ptr + nsize尚未定义的行为(感谢Sourav)。
为什么?该区域不再属于您的程序。
您可能会有错误读取新的较小数组,如果存在旧数据,这将产生有效结果,这可能是正确的,但是:
ptr不同ptr,因此某些人会忽略返回值并“起作用”直到崩溃),在这种情况下,后面是完整的无关数据。如果以上两个条件都没有发生,则数据很可能不变。realloc不会将不应使用的某些内存设置为0。一些调试框架(我不记得的那些调试框架)在释放内存时放了一个模式,因此,如果您在程序中偶然发现此模式,则很明显地表明您正在读取未分配/未初始化的内存,但是它有开销,因此默认情况下未完成。您也可以自己“超载”内存分配功能。
无论如何,请确保您没有读过新数组,因为不能保证您会找到所得到的内容。
首先,
void **ptr = realloc(ptr, nsize);
Run Code Online (Sandbox Code Playgroud)
是错误的,因为您使用的是ptr未初始化的(在此处定义),并且根据§7.22.3.5章中的realloc()功能描述C11
如果
ptr为null指针,则该realloc函数的行为类似于malloc指定大小的函数。否则,如果ptr与内存管理函数先前返回的指针不匹配,或者如果通过调用free或reallocfunction 释放了空间 ,则该行为是不确定的。[...]
因此,当您传递包含不确定值的指针时,您的代码将调用未定义的行为。
但是,考虑到您的情况是
void **ptr = malloc(size);
assert (ptr);
ptr = realloc(ptr, nsize);
Run Code Online (Sandbox Code Playgroud)
这是一种非常糟糕的用法,以防万一realloc失败(它不会更改原始内存并返回NULL),您最终也将丢失实际的指针。使用中间变量来存储验证返回的指针,然后根据需要将其分配回原始变量。
也就是说,重新检查报价(重点是我的)
该
realloc()函数将指向的存储块的大小更改ptr为size字节。从区域开始到新旧大小的最小值之间的内容将保持不变。如果新的大小大于旧的大小,则不会初始化添加的内存。
所以,要回答
如果原始大小为
size,是否表示ptr + nsize + 1仍包含分配的条目?
不,我们不能说。realloc()通话成功后,我们最多只能访问ptr + nsize - 1。尝试读/写ptr + nsize及后续操作未定义,因为该内存位置不再属于您的进程,并且该内存位置为“无效”。
无论如何,您都不需要去烦恼其他内容ptr + nsize - 1。