解决OI中使用g++编译器时出现的Segmentation fault错误

背景

我习惯于使用VScode刷一些算法题,但是很多时候在本地需要开大内存的时候(具体来说是在主函数里面),运行的时候IDE会提示Segmentation fault

比如以下代码:

1
2
3
4
5
6
7
#include <bits/stdc++.h>
using namespace std;
int main()
{
int blocks[1001][1001]{0};
...
}

这时候这个数组实际上仅仅占用了1001 * 1001 * 8B ≈7.64MB的内存,但是却出现了Segmentation fault错误。但是在OJ上面是没有问题的,能够AC。

其实解决方法也很简单,不要定义在主函数里面,而是直接开全局变量就行了。但是本着打破砂锅问到底的精神,我对这个现象进行了一些探索。

解释

在C++的程序中,全局变量是存储在上的,而局部变量是存储在上的。如果在主函数里面定义, 当在主函数中定义一个大数组时,由于栈空间有限,很可能会导致栈溢出,从而出现Segmentation fault错误。

那为什么OJ上面又可以跑呢?

其实是可以通过设置连接器的传入参数,来自定义栈分配的内存大小上限的。

以我的VSCode中配置为例,在你的项目文件夹下的.vscode文件夹中,应该有一个tasks.json文件,在里面修改配置,在tasks.args添加以下命令:

1
-Wl,--stack,512000000

这个命令的含义:

  • -Wl: 表示后面是传给连接器的命令
  • --stack,512000000,设置栈的内存分配上限为512000000B

改完应该像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe 生成活动文件",
"command": "C:\\MinGW\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"-Wl,--stack,512000000"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "调试器生成的任务。"
}
],
"version": "2.0.0"
}

这样以后,就算主函数里面开大内存也不会报错了。