2

我认为应该工作的命令行: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 个堆栈帧。

4

1 回答 1

0

升级到 WSL2 解决了这个问题:https ://docs.microsoft.com/en-us/windows/wsl/install-win10

setrlimit sudo prlimit --stack=unlimited --pid $$; ulimit -s unlimited工作(链接器选项似乎无关紧要)。

于 2021-09-11T23:11:42.863 回答