vector<pair<int, unordered_set<int>>> 在为 pair 提供默认构造函数参数时给出分段错误

Posted

技术标签:

【中文标题】vector<pair<int, unordered_set<int>>> 在为 pair 提供默认构造函数参数时给出分段错误【英文标题】:vector<pair<int, unordered_set<int>>> gives segmentation fault when supplying default constructor argument for pair 【发布时间】:2016-09-24 18:48:11 【问题描述】:

** 编辑:默认构造函数不会导致问题。我已经在下面说明了原因。我已经标记并投票结束了这个问题,对现在有机会看到这篇文章的任何人表示歉意。 **

不起作用的代码

int n = numCourses;
vector<pair<int, unordered_set<int>>> graph(n, make_pair(0, unordered_set<int>())); // pair of how many edges go in, and set of its neighbors.
// We have to find our leaves:
bool leaf[n];
for(int i = 0; i < n; i++)
    leaf[i] = true;


for(auto p : prerequisites)
    graph[p.first].first++;
    graph[p.first].second.insert(0);
    leaf[p.second] = false;


vector<int> leaves;
for(int i = 0; i < n; i++)
    if(leaf[i])
        leaves.push_back(i);

我正在尝试构建一个具有一些不错属性的 DAG 图。我想在图中提供一个默认构造函数参数,使用 make_pair 将右值定义提供给图的第二个参数。第一个参数是向量的大小。我想传递一个右值,其中该对的第一个值为 0,所以当我增加 graph[p.first].first++ 时,我确定它是 0。

我试过这个,当它到达 graph[p.first].second.insert(0) 时,它会抛出一个段错误,但我不能 100% 确定它为什么会发生。

有效的代码

int n = numCourses;
vector<pair<int, unordered_set<int>>> graph(n); // NO MORE DEFAULT RVALUE
// We have to find our leaves:
bool leaf[n];
for(int i = 0; i < n; i++)
    leaf[i] = true;


for(auto p : prerequisites)
    graph[p.first].first++;
    graph[p.first].second.insert(0); 
    leaf[p.second] = false;


vector<int> leaves;
for(int i = 0; i < n; i++)
    if(leaf[i])
        leaves.push_back(i); // This causes a segfault if I don't change it.

所以问题实际上就在graph[p.first].second.insert(0) 之后。是我的布尔数组引起了问题。对困惑感到抱歉!我已将此帖子标记为被模组删除。

谢谢!

编辑:下面我添加了一些可运行的案例: 不会导致段错误:https://ideone.com/EdmSva 是否导致段错误:https://ideone.com/GHQfog

这是由于布尔数组访问越界。我应该明白这一点,但 我尝试使用一些打印语句来查看段错误发生的位置。它在之后的行上,我猜当发生段错误时,stdout 的缓冲区没有被刷新,所以对于之前的行,它也没有显示打印。我不会再使用 print 对我的错误进行二进制搜索以查找段错误 - 在这里学到了宝贵的一课。

【问题讨论】:

谁刚刚评论了主题标题的错字 - 谢谢!一大早还没喝咖啡呢,哈哈:) 是什么让你认为第二个有,你的话,“未定义的行为 - 我知道”是事实?如果您不提供,则调整大小的向量将使用值初始化参数。对你来说,每对都意味着 0 和空集。这不是你想要的吗?可以复制/粘贴/编译以展示您的问题的实际minimal, complete, verifiable example 将对您的问题大有帮助。 leaf 的非标准 VLA 对您没有任何好处,我们只能猜测您的 真正 问题是什么。如果是我,我会通过 valgrind 发送这个。 @WhozCraig 你是对的,我很抱歉。我在脚注中提供了一个 MVCE(尽管它不再重要了),我将来会这样做。我确实尝试过调试程序,我认为这是问题所在(尽管我大错特错了)。 【参考方案1】:

是的,您遗漏了一些东西 - 段错误与 graph 的初始化无关,它的工作方式与人们期望的完全一样。检查的简单示例:

#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;

int main() 
    // your code goes here
    int n = 5;
    vector<pair<int, unordered_set<int>>> graph(n, make_pair(0, unordered_set<int>()));
    graph[0].first = 1;
    graph[1].second.insert(5);
    graph[1].second.insert(6);
    for (auto&& p : graph) 
        std::cout << p.first << " " << p.second.size() << std::endl;
    
    return 0;

输出(或在此处运行:https://ideone.com/kSVSnA):

1 0
0 2
0 0
0 0
0 0

代码中一些未定义的行为和省略的位还有其他问题:)

【讨论】:

啊,好的-谢谢!我将检查根本原因并对这个问题进行编辑。 :)

以上是关于vector<pair<int, unordered_set<int>>> 在为 pair 提供默认构造函数参数时给出分段错误的主要内容,如果未能解决你的问题,请参考以下文章

vector<pair<int, unordered_set<int>>> 在为 pair 提供默认构造函数参数时给出分段错误

std::pair<vector<int>, double> 的初始化列表

为啥 std::array<std::pair<int,int>, 3> 不能使用嵌套初始化列表初始化,但 std::vector<std::pair<int,in

C++vector使用pair/tuple

std::vector<std::pair<int, float>> 和 void 错误

STL 排序不能很好地排序我的 vector<pair<int,int>>