int main[-1U] = {1};
这很简单。用
编译gcc foo.c
当我在后台lsof
挂起GCC时,至少我无法使用gcc & :
找到该文件,但二级存储空间<16> (硬盘)将被吃掉。
这是如何运作的?
答案 0 :(得分:7)
您可以使用简单的printf
:
printf("%zu\n", (size_t)-1U);
这会产生4294967295
(demo) - 足以在sizeof(int)
等于4
的系统上填充16Gb的内存。
要了解为什么在文件系统中占用这么多空间,请将foo
编译为目标文件,然后运行size
实用程序。
我修改了程序,将数组大小调整为1,000,000个元素。以下是您运行size
时获得的输出:
$ gcc -c foo.c
$ size -A -d foo.o
foo.o :
section size addr
__text 0 0
__data 4000000 0
Total 4000000
__data
段包含初始化数据。编译器填写它,因为您提供了{1}
初始化程序。如果省略它,磁盘上可执行文件的大小将缩小到几千字节,因为该数组将放入未初始化的段:
$ size -A -d foo.o
foo.o :
section size addr
__text 0 0
Total 0
答案 1 :(得分:4)
无符号算术的模数比给定类型的最大值多一个。
因此-1U
为-1 + MAX_UINT + 1
,在2^32-1
的架构上为unsigned == uint32_t
。如果你的sizeof(int) == 4
,
int x[-1U] = {1};
将需要4*(2^32-1) B =~ 16 GiB
存储,并且存储不会被删除,因为它不是全零。
您的x
为main
的事实不起作用(除了它是main
将允许链接器完成链接,即使这将导致损坏的可执行文件你的main
不是函数。)
int x[-1U] = {1};
int main(){}
也需要超过16GiB,这个例子应该被完美定义(只要你的实现可以处理一个大的数组),不像你的例子main
有一个它不应该有的类型。
答案 2 :(得分:1)
未初始化的静态分配数组通常会转到.bss
部分。它们被隐式初始化为零。这些数据不需要存储在二进制文件中,因为启动代码“知道”它应该在运行时将此部分初始化为全零。所以我们可以说未初始化的数组,即使静态分配也不会消耗二进制大小。
另一方面,初始化的数据(非零初始化),如您所示,将转到.data
部分。哪个是生成的二进制文件的一部分,因为初始化数据必须存储在某处。在您的情况下,您有sizeof(int) * UINT_MAX
(-1U = UINT_MAX
)初始化数据(可能等于16Gb),这些数据都会添加到生成的二进制文件中。
答案 3 :(得分:0)
也许,您的系统上启用了虚拟内存。因此,当您尝试在内存中分配16 GB的数据时,由于虚拟内存,硬盘上会出现这么大的文件。
16 GB,因为您要分配4294967295个大小为4的整数。