我尝试通过将一些否定参数传递给bad_alloc
来测试new[]
异常。当传递小的负数时,我得到了我所希望的 - bad_alloc
。但是,当传递-1
时,我可以看到我的对象被构造了数千次(我在构造函数中打印静态计数器),应用程序终止于segfault。
new[]
将有符号整数转换为size_t
,因此-1
是size_t
的最大值,-2
是maximum - 1
,依此类推。
那么为什么new[]
在收到一些巨大数字时会抛出异常,但是在收到size_t
的最大值时会尝试分配? 1111...1
的{{1}}和1111...0
之间有什么区别? :)
提前致谢!
答案 0 :(得分:17)
这是我的猜测:
在许多实现中,分配器将在分配的区域旁边放置一些元数据 (例如,分配的大小。)因此,实际上,您分配的内容超出了您的要求。
假设size_t
是32位。编译为32位。
当你这样做时:
int *array = new int[-1];
-1
变为-1 * 4 bytes = 4294967292
(溢出后)。但是,如果分配器实现将4字节的元数据放在分配的区域旁边。实际大小变为:
4294967292 + 4 bytes = 0 bytes (after overflow)
因此实际分配了0
个字节。
当您尝试访问内存时,由于您立即超出范围,因此会出现段错误。
现在让我们说:
int *array = new int[-2];
-2
变为-2 * 4 bytes = 4294967288
(溢出后)。附加4个字节的元数据,然后得到4294967288 + 4 = 4294967292
。
当分配器从操作系统请求4294967292
个字节时,它被拒绝。所以它抛出了bad_alloc
。
基本上,-1
和-2
可能会在分配器附加元数据后是否会溢出。