【问题标题】:Segmentation fault in C++ before entering main进入 main 之前 C++ 中的分段错误
【发布时间】:2021-06-30 10:34:13
【问题描述】:

这是一个很常见的问题,我尝试阅读解决方案,但似乎都没有解决我的问题。这是我写的代码,我知道它很乱,因为我是 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,它编译成功但没有运行。请帮帮我。

【问题讨论】:

  • 你的意思是main后面的前两行吗?他们应该关闭 C++ i/o 和 C i/o 之间的同步,对吗?
  • 我有点喜欢这样做,因为我可以一次输入所有输入,然后将输出放在一起,这使我检查我的解决方案非常方便。另外,我做有竞争力的编程(好吧,请不要开始),它看起来对大量输入很有帮助。
  • 因为当我删除它们时,当我有多个测试用例的输入时,只要我给出输入就会得到输出。是的,这里似乎不需要,但也许
  • int exist[n][n] - C++ doesn't support VLAs。此外,您需要包含&lt;array&gt;&lt;vector&gt; 才能使用std::arraystd::vector。我不确定你的编译器是如何编译所有这些而不给出一个错误的......
  • std::vector&lt;int&gt; adj[N]

标签: c++ segmentation-fault g++ main


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    首先,这不是有效的 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&lt;int&gt; adj[N];

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


    一种解决方案是使用std::vector&lt;std::vector&lt;int&gt;&gt;:

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

    由于向量从堆中获取内存,堆栈内存耗尽问题就消失了。

    【讨论】:

    • 谢谢。我自己更喜欢向量,但问题是声明多维向量比数组困难得多。另外,在使用 C++ 一年后,我今天意识到,我一直使用的语法是错误的。我很幸运。我想知道是否存在一些更简单的声明多维向量的方法。
    猜你喜欢
    • 2017-07-16
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 2015-10-13
    • 1970-01-01
    相关资源
    最近更新 更多