递归结构的向量有内存问题
Vector of recursive structures has memory problems
我完全被一段简单的代码所困扰,这段代码在内存上行为异常(正如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;
}
我希望它创建一个包含 2 个结构的数组,第一个结构有一个指向第二个结构的指针。真正的来源在破坏时因段错误而崩溃,因此我认为这份报告很重要:
==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)
一旦您push_back向量或以其他方式更改它,所有指向存储项目的引用和指针都将失效,因此所有tail
和next
字段都将包含悬空指针。取消引用它们将导致未定义的行为。您实际上可以使用std::list
或者(如果您只是出于学习目的编写一些列表实现(,您可以首先填充向量,然后收集指向存储项的指针,知道它们将保持有效。
相关文章:
- C++ 中 std::vector 的内存问题
- 实现快速排序的内存问题
- 此add_node函数会导致内存问题吗?
- C++:为什么这段代码给我内存问题/未定义的行为?
- 我不明白附加字符串的内存问题
- 是否有可能存在不会崩溃程序的内存问题
- 在发布版本中删除类指针会导致内存问题
- Android OpenCV 应用程序的内存问题
- 线程的内存问题(微小线程,C++)
- 递归结构的向量有内存问题
- C++合并排序内存问题
- 将智能指针发送到Protobaf.内存问题
- 潜在的动态内存问题
- JNI 中的内存问题
- C++Lambda函数关闭-内存问题
- 解决由全局静态变量引起的内存问题
- 类堆栈内存问题(致命错误)
- QNetworkAccessManager内存问题
- 读取进程内存问题未更新
- 类指针内存问题