进入 main 之前 C++ 中的分段错误

Segmentation fault in C++ before entering main

这是一个很常见的问题,我尝试阅读解决方案,但其中 none 似乎解决了我的问题。这是我写的代码,我知道它很乱,因为我是 C++ 的新手。

#include<iostream>
#include<string>
#include<iomanip>
#include<set>
#include<queue>
#include<cmath>
#include<algorithm>
#include<vector>
#include<limits.h>
#include<math.h>
#include<map>
#include<cstring>
using ll = long long;
const int N = 2e6+6;

int main(){
    std::ios_base::sync_with_stdio(0);
    std::cin.tie(0);
    int n,m;
    std::cin >> n >> m;
    std::vector<std::array<int,3>> edges;
    int exist[n][n];
    memset(exist,0,sizeof(exist));
    for(int i = 0; i < m;++i){
        int a,b;
        char c;
        std::cin >> a >> b >> c;
        --a,--b;
        edges.push_back({a,b,c-'a'});
        exist[a][b] = exist[b][a] = 1;
    }
    std::vector<int> adj[N];
    std::map<std::pair<int,int>,int> nodes;
    int node = 0;
    for(int i = 0; i < m;++i){
        for(int j = 0; j < m;++j){
            if(i == j)
                continue;
            if(edges[i][2] != edges[j][2])
                continue;
            int a = edges[i][0];
            int b = edges[i][1];
            int c = edges[j][0];
            int d = edges[j][1];
            if(nodes[{a,c}] == 0)
                nodes[{a,c}] = ++node;
            if(nodes[{b,d}] == 0)
                nodes[{b,d}] = ++node;
            if(nodes[{a,d}] == 0)
                nodes[{a,d}] = ++node;
            if(nodes[{b,c}] == 0)
                nodes[{b,c}] = ++node;
            adj[nodes[{a,c}]].push_back(nodes[{b,d}]);
            adj[nodes[{b,d}]].push_back(nodes[{a,c}]);
            adj[nodes[{a,d}]].push_back(nodes[{b,c}]);
            adj[nodes[{b,c}]].push_back(nodes[{a,d}]);
        }
    }
    int start = nodes[{0,n-1}];
    int ans = 1e9+7;
    std::queue<int> q;
    q.push(start);
    std::vector<int> dist(node+1,-1);
    dist[start] = 0;
    std::vector<bool> visited(node+1,false);
    visited[start] = true;
    auto it = nodes.begin();
    while(!q.empty()){
        int cur_node = q.front();
        q.pop();
        for(int i = 0; i < (int)adj[cur_node].size();++i){
            int next_node = adj[cur_node][i];
            if(!visited[next_node]){
                q.push(next_node);
                visited[next_node] = true;
                dist[next_node] = dist[cur_node] + 1;
            }
        }
    }
    for(int i = 0; i < n;++i){
        for(int j = 0; j < n;++j){
            int node = nodes[{i,j}];
            if(node == 0)
                continue;
            if(dist[node] == -1)
                continue;
            if(i == j || (exist[i][j] == 1)){
                ans = std::min(ans,dist[node]);
            }
        }
    }
    if(ans == 1e9+7)
        ans = -1;
    std::cout << ans << "\n";
}


这个程序甚至在进入 main 之前就给出了分段错误,我尝试使用 gdb,它也说错误在 int main() 行。我完全不明白发生了什么,我也尝试 运行 在 C++ 14 和 C++ 17 上运行程序,它 运行 很好,但我使用的是 C++ 11,它编译成功但没有't 运行。请帮助我。

您在堆栈中的代码中分配了超过 200 万 std::vectors。通常堆栈不是很大,所以肯定会超过保留的 space 并导致问题。局部对象的分配发生在函数中的任何代码 运行 之前,因此看起来它在函数中崩溃但在您的任何代码 运行.

之前
std::vector<int> adj[N];

如果您需要那么多向量,则需要动态分配它。

首先,这不是有效的 C++:

int n;
cin >> n;
int exist[n][n];  // <-- not valid C++

C++ 中的数组的大小必须由编译时表达式表示,而不是运行时值。 C++ does not support variable-length arrays.

已编译的代码,因为有些编译器默认支持此功能。但它仍然不受 C++ 语言规范的支持。例如,Visual C++ 编译器不支持这种语法。如果您尝试使用 Visual C++ 编译代码,您会收到相应的错误消息。

即使支持,较大的 n 值也可能会破坏堆栈内存,因为堆栈内存是有限的。

那么第二个问题就是你有这个:

std::vector<int> adj[N];

如果N很大,那就是Nstd::vector<int>的数组。同样,这很可能会耗尽堆栈内存。


一种解决方案是使用 std::vector<std::vector<int>>:

std::vector<std::vector<int>> exist(n, std::vector<int>(n));
//...
std::vector<std::vector<int>> adj(N):

由于 vector 从堆中获取内存,因此堆栈内存耗尽问题消失了。