编译文件过大[202493852字节]在线提交错误
在使用二维数组时,我尝试使用静态数组将 -1 分配给它的第一个元素:
int dp[5001][5001] = {-1}; //setting dp[0][0] to -1
int calc(int i, int j){
//Some operations are happening here which utilize dp array.
}
int main(){
cout << calc(0,0);
}
当我将此代码片段作为在线解决方案提交时,我得到Can't compile file: Compiled file is too large [202493852 bytes].
但是,当我通过在 main() 中设置 dp 的值来尝试一下时
int dp[5001][5001];
int calc(int i, int j){
//Some operations are happening here which utilize dp array.
}
int main(){
dp[0][0] = -1;
cout << calc(0,0);
}
上面的代码片段被成功接受并编译。
有人可以解释为什么会这样吗?
回答
当您使用初始化程序声明静态数组时,例如
int dp[5001][5001] = {-1};
整个数组被放入可执行文件的数据部分。它的大小是 (5001×5001=25010001) ×sizeof(int)你的编译器。如果sizeof(int)==8,则以字节为单位的数组大小 200080008 接近您引用的限制。最后,二进制文件中还有其他内容。
另一方面,第二个示例中没有初始化程序的数组
int dp[5001][5001];
未在可执行文件中分配任何数据空间;取而代之的是,只有一个小记录告诉加载程序在进程启动时在进程的地址空间中分配这个大小的零初始化内存块。
这种优化不是强制性的,但 ELF 和 Windows PE 二进制文件都使用它。初始化的数据段通常称为.data,未初始化的.bss.
一个展示概念的小动手实验¹:
// Save me as bss.cc
int without_initializer[10000][10000]; // 100 million elements.
int with_initializer[1000][1000] = { 42 }; // 1 million elements.
/*
Run and see:
$ c++ -c -o bss.o bss.cc
$ ls -l bss.o
-rw-r--r-- 1 kkm kkm 4001008 2021-05-18 06:00:19 bss.o
$ objdump -h bss.o
bss.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 003d0900 0000000000000000 0000000000000000 00000040 2**5
CONTENTS, ALLOC, LOAD, DATA
2 .bss 17d78400 0000000000000000 0000000000000000 003d0940 2**5
ALLOC
3 .comment 0000001d 0000000000000000 0000000000000000 003d0940 2**0
CONTENTS, READONLY
$ rm bss.cc bss.o
*/
该.data部分的大小为 0x3d0900=4000000 字节。显然,这个编译器sizeof(int)是 4。它也有LOAD标志,这意味着它必须从文件中加载,正如链接的答案中所解释的那样。
ls(1) 显示目标文件的大小只比同样的 4000000 字节大一点,头和小.comment部分占用了一点额外的空间,可能识别编译器(objdump(1) 可以转储其内容,如果你很好奇)。
该.bss部分的大小为 0x17d78400=400000000,完全相等sizeof(without_initializer)。它有ALLOC标志告诉加载器它必须在进程的地址空间中,但没有LOAD标志,这意味着没有任何东西可以从文件加载。
您可能会注意到该.bss部分在文件中正好占据了 0 个字节:它的偏移量和以下.comment部分的偏移量都是 0x003d0940。
¹ 使用 Linux 命令及其 ELF 格式。在 Windows 上,如果您有 Visual Studio ,请从Native Tools 命令提示符使用cl /c bss.ccthen 。dumpbin /headers bss.obj