对向量使用 Push Back 功能时的分段错误

Posted

技术标签:

【中文标题】对向量使用 Push Back 功能时的分段错误【英文标题】:Segmentation Fault When Using The Push Back Function for a Vector 【发布时间】:2019-11-10 08:20:20 【问题描述】:

因此,我尝试从头开始使用自定义哈希函数构建哈希表,但在测试插入函数时遇到了分段错误问题。如果我正确读取了 gdb 输出,则在我的 wn_to_bool 函数中尝试对布尔向量进行推回时会出现问题(取一个整数并将其转换为布尔向量)。我一直在尝试调试这个问题一段时间,但还没有找到解决方案。任何帮助将不胜感激,如有必要,我可以使用调试中引用的其余代码更新帖子。提前谢谢你。

没有新操作符的 GDB 输出

Program received signal SIGSEGV, Segmentation fault.
0x000055555555668b in std::vector<bool, std::allocator<bool> >::push_back (this=0x0, __x=false) at /usr/include/c++/9.2.0/bits/stl_bvector.h:955
955             if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr())
(gdb) bt
#0  0x000055555555668b in std::vector<bool, std::allocator<bool> >::push_back (this=0x0, __x=false) at /usr/include/c++/9.2.0/bits/stl_bvector.h:955
#1  0x0000555555556302 in HashTable<int, int>::wn_to_bool (this=0x7fffffffe3f0, wn=2) at Data_Structures/Hash_Table.cpp:186
#2  0x0000555555556230 in HashTable<int, int>::hashfct (this=0x7fffffffe3f0, key=2) at Data_Structures/Hash_Table.cpp:146
#3  0x0000555555556163 in HashTable<int, int>::insert (this=0x7fffffffe3f0, key=2, value=3) at Data_Structures/Hash_Table.cpp:53
#4  0x0000555555555b0f in main (argc=1, argv=0x7fffffffe4f8) at main.cpp:16

带有新运算符的 GDB 输出

Program received signal SIGABRT, Aborted.
0x00007ffff7ab8f25 in raise () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff7ab8f25 in raise () from /usr/lib/libc.so.6
#1  0x00007ffff7aa2897 in abort () from /usr/lib/libc.so.6
#2  0x00007ffff7b03758 in __malloc_assert () from /usr/lib/libc.so.6
#3  0x00007ffff7b05f6f in sysmalloc () from /usr/lib/libc.so.6
#4  0x00007ffff7b06d32 in _int_malloc () from /usr/lib/libc.so.6
#5  0x00007ffff7b07e84 in malloc () from /usr/lib/libc.so.6
#6  0x00007ffff7e47cba in operator new (sz=40) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/new_op.cc:50
#7  0x000055555555633d in HashTable<int, int>::wn_to_bool (this=0x7fffffffe3f0, wn=2) at Data_Structures/Hash_Table.cpp:181
#8  0x0000555555556230 in HashTable<int, int>::hashfct (this=0x7fffffffe3f0, key=2) at Data_Structures/Hash_Table.cpp:146
#9  0x0000555555556163 in HashTable<int, int>::insert (this=0x7fffffffe3f0, key=2, value=3) at Data_Structures/Hash_Table.cpp:53
#10 0x0000555555555b0f in main (argc=1, argv=0x7fffffffe4f8) at main.cpp:16

wn_to_bool 函数请注意 v 最初是一个空向量,因此插入函数将不起作用

template <typename K, typename V> std::vector<bool>* HashTable<K,V>::wn_to_bool(long wn)

    std::vector<bool>* v;

    while(wn != 0)
    
        if(wn % 2 == 0)
            v->push_back(false);
        else
            v->push_back(true);

        wn = wn / 2;
    

    return v; 

【问题讨论】:

v 未初始化,您有一个悬空指针 => 未定义的引用。为什么要使用指向向量的指针?还要小心,vector&lt;bool&gt; 比较奇怪。 "获取一个整数并将其转换为布尔向量" 这是相当可疑的实用程序。为什么需要布尔向量? 【参考方案1】:

请注意 v 最初是一个空向量

事实并非如此。它是一个未初始化的指针。看不到实际的向量。

不要使用原始指针。

抛开这种函数的实用性不谈,这里有一种写法。

template <typename K, typename V> 
std::vector<bool> // no pointer
HashTable<K,V>::wn_to_bool(long wn)

    std::vector<bool> v; //no pointer
    while(wn != 0)
    
        if(wn % 2 == 0)
            v.push_back(false);
        else
            v.push_back(true);
        wn = wn / 2;
    
    return v; 

因此插入功能将不起作用)

insert 非常适用于空向量,例如 vector&lt;int&gt; v; v.insert(v.begin(), 42)

【讨论】:

对不起,插入在哪里?您在回溯中看到的插入方法适用于 HashTable 类,但不适用于 std::vector。本题与insert方法无关。 @SoheilArmin OP 错误地声称insert 不适用于空的向量。我正在处理这个声明。 很明显,空向量是begin()等于end()push_back实际上意味着insert(end(),val)的向量。所以你是绝对正确的。【参考方案2】:

当您执行std::vector&lt;bool&gt;* v 时,您将有一个指向std::vector&lt;bool&gt; 的未初始化指针。这意味着v 具有一些任意值,而没有分配给任何已分配的内存地址。 您需要创建一个new 向量并将其分配给v

template <typename K, typename V> std::vector<bool>* HashTable<K,V>::wn_to_bool(long wn)

    auto v = new std::vector<bool>();

    for(;wn!=0;wm/=2)
        v->push_back(wn % 2 != 0);

    return v; 

您不需要if 语句,因为您直接使用布尔语句的结果。您只需要推回wn%2 != 0,这比使用if 更有效。您也可以使用for 循环来提高可读性,因为您将在一行代码中编写整个逻辑。

根据 cmets 的建议,在堆内存中创建对象实例(也就是使用 new)应该非常小心,因为当您不再需要分配的内存时,您必须小心删除它,否则它会导致内存泄漏。强烈建议改用smart pointers

【讨论】:

对不起,之前没有更具体,但我确实使用你的方法和 std::vector *v = new std::vector 尝试了 new 运算符,但它们导致中止在上面的 gdb 输出中描述(使用 new 运算符)。 @patelvrajn 根据您公开的代码(恕我直言),答案是正确的。如果您尝试了其他效果不佳的方法-那是另一个问题。 请注意 v 最初是一个空向量,因此插入函数将不起作用 不,它不是一个空向量,它是一个未初始化的指针(如正确指出的那样)。插入一个最初为空的向量应该可以工作。 @Scheff 如果向量为空(在这种情况下不包含布尔值),则根据 STD 文档插入不起作用。插入操作需要一个迭代器,如果没有对象指向,迭代器就不能指向任何地方。 请不要建议毫无戒心的新手使用 new 和指针。这不是一个好主意。 这就是问题所在,当教孩子们将 Java 作为他们的第一语言时……一切都是“新的”:)

以上是关于对向量使用 Push Back 功能时的分段错误的主要内容,如果未能解决你的问题,请参考以下文章

在某些循环内使用 vector.push_back 时出现分段错误

push_back 上的分段错误[关闭]

使用向量 push_back 分配内存

为啥这个向量代码会出现分段错误?

在 C++ 中的向量中键入所有值后出现分段错误(核心转储)

推送到成员向量时的段错误