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