c++ - 编译文件过大【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 ,请从本机工具命令提示符cl /c bss.cc
使用then 。dumpbin /headers bss.obj
推荐阅读
- c++ - 尝试编译脚本 C++ 时出错 - Unreal Engine 5
- elasticsearch - ElasticSearch函数得分查询(范围过滤)
- excel - 如何根据excel vba中的组合框值设置文本框的最小值?
- python - 使用带有 Python 可执行文件的配置文件
- c# - 无法向游戏对象添加任何组件
- javascript - 无法使用 Jest 正确模拟 API 调用
- ios - Swift:将 const char ** 输出参数转换为字符串
- flutter - 使用 FlutterBlue 获取特征的“句柄”?
- tfs - SonarQube 新代码分析延迟 5 小时
- php - 如果在 5 分钟内没有添加任何行,则插入 MySQL 表