【发布时间】:2015-11-05 15:52:36
【问题描述】:
我在试验realloc,给它越来越大的尺寸,并检查同一个块是否被重用:
int main ( void )
{
char * newstr, * prevstr = NULL;
size_t newsize, prevsize = 0;
printf ("We play with realloc\n");
while (1) {
newsize = prevsize + 1 + prevsize/3; /* add 33% */
newstr = realloc(prevstr, newsize);
if (newstr == NULL) {
printf ("could not alloc newsize=%zu. Sorry\n", newsize);
break;
} else {
printf ("newsize=%zu successfully alloc'ed\n", newsize);
if (newstr == prevstr) {
printf ("newstr = prevstr:\tSame block reused\n");
} else {
printf ("newstr != prevstr:\tNew block alloc'ed\n");
}
prevstr = newstr; prevsize = newsize;
}
}
return (EXIT_SUCCESS);
}
正如预期的那样,最终会达到尺寸太大而realloc 无法响应请求的地步。根据手册,realloc 不成功时应该返回NULL 并设置errno = ENOMEM。
当我在我的机器上运行上述代码时不会发生这种情况,这是一台带有“Darwin Kernel Version 15.0.0”的 Mac。 代码没有返回NULL,而是崩溃并说
malloc: *** mach_vm_map(size=153288611651584) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
could not alloc newsize=153288611651277. Sorry
这正常吗?阅读手册页时有什么我不明白的地方?
目前这对我的代码来说并不重要,但我可以想象在哪些情况下我想测试是否可以分配内存而不会有崩溃的风险。有没有一种标准的方法来测试 alloc 是否可以工作而不会冒这种崩溃的风险?
解开谜团后添加(见下面的答案):没有崩溃,只是一些来自 malloc 的系统错误消息妨碍了预期的输出。请参阅下文,了解如何避免这种情况。
【问题讨论】:
-
这里好像有些东西不符合标准..
-
它似乎并没有真正崩溃。它只是输出一些额外的诊断信息并返回 NULL(当
newstr == NULL时,您的代码会打印消息“无法分配新大小”)。 -
好点。真的会崩溃吗?
-
我相信它会转到
stderr,你可以重定向它。或者甚至使用一些宏将其关闭。类似here -
@Kevin 是的。 C11 6.2.4p2:“当指针指向(或刚刚过去)的对象到达其生命周期的尽头时,指针的值变得不确定”。 “不确定值”在 3.19.2 中定义为可能有效。 (基本上听起来像 C 不遗余力地允许
malloc&c. 重用位置,而无需 GC 所有对它们的引用。)因此允许比较本身(6.5.9 中没有 UB),但不能保证产生有意义的结果。
标签: c memory-management malloc