我认为应该工作的命令行:g++ -std=c++17 -O3 -Wl,-z,stack-size=1000000000 C.cc && ./a.out < C.2
它不是工作,而是段错误。-fsanitize=address将问题标识为堆栈溢出。
我发现https://github.com/microsoft/WSL/issues/633表明sudo prlimit --stack=unlimited --pid $$; ulimit -s unlimited哪个“有效”;ulimit -s现在打印“无限”。但我仍然得到段错误。我希望上面的链接器选项可以工作,但他们没有。我还尝试直接在 C++ 代码中使用 setrlimit:
struct rlimit rl;
assert(0 == getrlimit(RLIMIT_STACK, &rl));
rl.rlim_cur = 3LL*1024*1024*1024;
assert(0 == setrlimit(RLIMIT_STACK, &rl));
assert(0 == getrlimit(RLIMIT_STACK, &rl));
cerr << rl.rlim_cur << endl;
最后一行打印 3GB,但我仍然得到堆栈溢出。
具有溢出的函数是具有以下签名的递归树 DFS ll root(ll x, const vector<vector<pll>>& E, vector<ll>& P, vector<ll>& SZ) {:. 树的深度是<= 800,000,所以我认为 AFAIK 所需的总堆栈大小应该是8*800,000*4字节,大约 30 MB。所以应该可以让它运行。
我想不出还有什么可以尝试的。有任何想法吗?我在 Ubuntu 中使用 WSL 版本 1。
==========================================
这是一个简单的复制。将以下代码另存为ex.cc:
#include <iostream>
#include <sys/resource.h>
#include <cassert>
using namespace std;
using ll = int64_t;
ll f(ll n) {
if(n==0) { return 0LL; }
return n + f(n-1);
}
int main() {
struct rlimit rl;
assert(0 == getrlimit(RLIMIT_STACK, &rl));
rl.rlim_cur = 3LL*1024*1024*1024;
assert(0 == setrlimit(RLIMIT_STACK, &rl));
assert(0 == getrlimit(RLIMIT_STACK, &rl));
cerr << rl.rlim_cur << endl;
cout << f(1e6) << endl;
}
g++ -std=c++17 -Wl,-z,stack-size=1000000000 ex.cc -fsanitize=address && ./a.out给出堆栈溢出(也没有-fsanitize=address)。对我来说,它失败了大约 262,000 个堆栈帧。