Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 递归结构的向量存在内存问题_C++_Memory_Valgrind_Recursive Datastructures - Fatal编程技术网

C++ 递归结构的向量存在内存问题

C++ 递归结构的向量存在内存问题,c++,memory,valgrind,recursive-datastructures,C++,Memory,Valgrind,Recursive Datastructures,我完全被一段简单的代码卡住了,这段代码在内存中表现不好(正如Valgrind所报告的)。我将其简化为以下简短的测试用例: #include <vector> struct el { el * next = nullptr; }; class list { public: list(): tail(nullptr) {} void push_back() { el nw; m_list.push_back(nw);

我完全被一段简单的代码卡住了,这段代码在内存中表现不好(正如Valgrind所报告的)。我将其简化为以下简短的测试用例:

#include <vector>

struct el
{
    el * next = nullptr;
};

class list
{
public:
    list(): tail(nullptr) {}

    void push_back()
    {
        el nw;
        m_list.push_back(nw);

        if (tail == nullptr)
            tail = &m_list.back();
        else
        {
            tail->next = &m_list.back();
            tail = tail->next;
        }
    }

private:
    std::vector<el> m_list;
    el * tail;
};

int main()
{
    list a;
    a.push_back();
    a.push_back();
    return 0;
}
#包括
结构el
{
el*next=nullptr;
};
班级名单
{
公众:
list():tail(nullptr){}
void push_back()
{
西北偏北;
m_列表。推回(nw);
if(tail==nullptr)
tail=&m_list.back();
其他的
{
tail->next=&m_list.back();
tail=tail->next;
}
}
私人:
std::向量m_列表;
el*尾部;
};
int main()
{
清单a;
a、 向后推();
a、 向后推();
返回0;
}
我希望它创建一个包含两个结构的数组,第一个结构有一个指向第二个结构的指针。真正的源崩溃与分段故障,所以我认为这份报告很重要:

==1630== Invalid write of size 8
==1630==    at 0x400A37: list::push_back() (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400969: main (in /home/ilya/Projects/algos/a.out)
==1630==  Address 0x5a86c80 is 0 bytes inside a block of size 8 free'd
==1630==    at 0x4C2A8DC: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1630==    by 0x4011D5: __gnu_cxx::new_allocator<el>::deallocate(el*, unsigned long) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400F79: std::_Vector_base<el, std::allocator<el> >::_M_deallocate(el*, unsigned long) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400DA3: void std::vector<el, std::allocator<el> >::_M_emplace_back_aux<el const&>(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400B42: std::vector<el, std::allocator<el> >::push_back(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x4009FF: list::push_back() (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400969: main (in /home/ilya/Projects/algos/a.out)
==1630==  Block was alloc'd at
==1630==    at 0x4C29780: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1630==    by 0x4012BB: __gnu_cxx::new_allocator<el>::allocate(unsigned long, void const*) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x4010D2: std::_Vector_base<el, std::allocator<el> >::_M_allocate(unsigned long) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400CC1: void std::vector<el, std::allocator<el> >::_M_emplace_back_aux<el const&>(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400B42: std::vector<el, std::allocator<el> >::push_back(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x4009FF: list::push_back() (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x40095D: main (in /home/ilya/Projects/algos/a.out)
==1630==
==1630== Invalid read of size 8
==1630==    at 0x400A42: list::push_back() (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400969: main (in /home/ilya/Projects/algos/a.out)
==1630==  Address 0x5a86c80 is 0 bytes inside a block of size 8 free'd
==1630==    at 0x4C2A8DC: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1630==    by 0x4011D5: __gnu_cxx::new_allocator<el>::deallocate(el*, unsigned long) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400F79: std::_Vector_base<el, std::allocator<el> >::_M_deallocate(el*, unsigned long) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400DA3: void std::vector<el, std::allocator<el> >::_M_emplace_back_aux<el const&>(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400B42: std::vector<el, std::allocator<el> >::push_back(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x4009FF: list::push_back() (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400969: main (in /home/ilya/Projects/algos/a.out)
==1630==  Block was alloc'd at
==1630==    at 0x4C29780: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==1630==    by 0x4012BB: __gnu_cxx::new_allocator<el>::allocate(unsigned long, void const*) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x4010D2: std::_Vector_base<el, std::allocator<el> >::_M_allocate(unsigned long) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400CC1: void std::vector<el, std::allocator<el> >::_M_emplace_back_aux<el const&>(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x400B42: std::vector<el, std::allocator<el> >::push_back(el const&) (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x4009FF: list::push_back() (in /home/ilya/Projects/algos/a.out)
==1630==    by 0x40095D: main (in /home/ilya/Projects/algos/a.out)
==1630==大小为8的无效写入
==1630==at 0x400A37:list::push_back()(in/home/ilya/Projects/algos/a.out)
==1630==by 0x400969:main(in/home/ilya/Projects/algos/a.out)
==1630==地址0x5a86c80是大小为8 free'd的块中的0字节
==1630==at 0x4C2A8DC:运算符删除(void*)(在/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so中)
==1630==by 0x4011D5:u gnu_cxx::新的_分配器::解除分配(el*,无符号长)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x400F79:std::_Vector_base::_M_deallocate(el*,无符号长)(in/home/ilya/Projects/algos/a.out)
==1630==0x400DA3:void std::vector::_M_emplace_back_aux(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==0x400B42:std::vector::push_back(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x4009FF:list::push_back()(in/home/ilya/Projects/algos/a.out)
==1630==by 0x400969:main(in/home/ilya/Projects/algos/a.out)
==1630==块在
==1630==在0x4C29780处:新运算符(无符号长)(在/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so中)
==1630==by 0x4012BB:uu gnu_cxx::新的_分配器::分配(无符号长,无效常量*)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x4010D2:std::_Vector_base::_M_allocate(无符号长)(in/home/ilya/Projects/algos/a.out)
==1630==0x400CC1:void std::vector::_M_emplace_back_aux(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==0x400B42:std::vector::push_back(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x4009FF:list::push_back()(in/home/ilya/Projects/algos/a.out)
==1630==by 0x40095D:main(in/home/ilya/Projects/algos/a.out)
==1630==
==1630==大小为8的无效读取
==1630==at 0x400A42:list::push_back()(in/home/ilya/Projects/algos/a.out)
==1630==by 0x400969:main(in/home/ilya/Projects/algos/a.out)
==1630==地址0x5a86c80是大小为8 free'd的块中的0字节
==1630==at 0x4C2A8DC:运算符删除(void*)(在/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so中)
==1630==by 0x4011D5:u gnu_cxx::新的_分配器::解除分配(el*,无符号长)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x400F79:std::_Vector_base::_M_deallocate(el*,无符号长)(in/home/ilya/Projects/algos/a.out)
==1630==0x400DA3:void std::vector::_M_emplace_back_aux(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==0x400B42:std::vector::push_back(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x4009FF:list::push_back()(in/home/ilya/Projects/algos/a.out)
==1630==by 0x400969:main(in/home/ilya/Projects/algos/a.out)
==1630==块在
==1630==在0x4C29780处:新运算符(无符号长)(在/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so中)
==1630==by 0x4012BB:uu gnu_cxx::新的_分配器::分配(无符号长,无效常量*)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x4010D2:std::_Vector_base::_M_allocate(无符号长)(in/home/ilya/Projects/algos/a.out)
==1630==0x400CC1:void std::vector::_M_emplace_back_aux(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==0x400B42:std::vector::push_back(el const&)(in/home/ilya/Projects/algos/a.out)
==1630==by 0x4009FF:list::push_back()(in/home/ilya/Projects/algos/a.out)
==1630==by 0x40095D:main(in/home/ilya/Projects/algos/a.out)

一旦您将u推回向量或以其他方式更改它,所有指向存储项的引用和指针都将无效,因此所有
尾部
下一个
字段将包含悬空指针。取消对它们的引用将导致未定义的行为。实际上,您可以使用
std::list
或(如果您只是为了学习而编写一些列表实现)您可以先填充vector,然后收集指向存储项的指针,知道它们将保持有效。

一旦您将_推回vector或以其他方式更改它,所有指向存储项的引用和指针都将无效,因此所有
尾部
下一个
字段将包含悬空指针。取消对它们的引用将导致未定义的行为。实际上,您可以使用
std::list
,或者(如果您只是为了学习而编写一些列表实现),您可以先填充vector,然后收集指向存储项的指针,知道它们将保持有效。

您不能获取vector元素的地址并将其隐藏,因为下一个向量操作可能会使其无效。所以
tail->next=&m_list.back()
是3/5的禁止规则,矢量元素在内存中不稳定。您不能获取矢量元素的地址并将其隐藏起来,因为下一个矢量操作可能会使其无效。所以
tail->next=&m_list.back()
是3/5的禁忌规则,并且向量元素在内存中不稳定。哦,这是由增长时的向量重新分配引起的吗?@Ilya Yes一旦重新定位存储(实际上在收缩时也会发生这种情况),指向前一个存储的指针就会失效。您应该检查向量方法的文档,以确定哪些方法无效