【问题标题】:Large scale deletions from STL vector crashing my binary从 STL 向量中大规模删除使我的二进制文件崩溃
【发布时间】:2013-05-22 15:53:36
【问题描述】:

我的二进制文件崩溃了。在运行核心转储时,我发现以下内容:

#0  0x00a6a363 in memmove () from /lib/tls/libc.so.6
(gdb) frame 1
#1  0x083a108c in std::__copy_trivial<piola::piolaOrderBook*> (__first=0xb277f2c4, __last=0xb277f2bc, __result=0xb277f2c0)
    at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_algobase.h:258
258           std::memmove(__result, __first, sizeof(_Tp) * (__last - __first));
(gdb) frame 2
#2  0x083a0ad6 in std::__copy_aux2<piola::piolaOrderBook*> (__first=0xb277f2c4, __last=0xb277f2bc, __result=0xb277f2c0)
    at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_algobase.h:279
279         { return std::__copy_trivial(__first, __last, __result); }
(gdb) frame 3
#3  0x083a02d1 in std::__copy_ni2<piola::piolaOrderBook**, __gnu_cxx::__normal_iterator<piola::piolaOrderBook**, std::vector<piola::piolaOrderBook*, std::allocator<emapi::EmapiOrderBook*> > > > (__first=0xb277f2c4, __last=0xb277f2bc, __result=
      {_M_current = 0xb277f2c0})
    at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_algobase.h:296
296           return _OutputIterator(std::__copy_aux2(__first, __last, __result.base(),
(gdb) frame 4
#4  0x0839f1b0 in std::__copy_ni1<__gnu_cxx::__normal_iterator<piola::piolaOrderBook**, std::vector<piola::piolaOrderBook*, std::allocator<piola::piolaOrderBook*> > >, __gnu_cxx::__normal_iterator<piola::piolaOrderBook**, std::vector<piola::piolaOrderBook*, std::allocator<piola::piolaOrderBook*> > > > (__first={_M_current = 0xb277f2c4}, __last=
      {_M_current = 0xb277f2bc}, __result={_M_current = 0xb277f2c0})
    at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_algobase.h:317
317           return std::__copy_ni2(__first.base(), __last.base(),
(gdb) frame 5
#5  0x0839d676 in std::copy<__gnu_cxx::__normal_iterator<piola::piolaOrderBook**, std::vector<piola::piolaOrderBook*, std::allocator<piola::piolaOrderBook*> > >, __gnu_cxx::__normal_iterator<piola::piolaOrderBook**, std::vector<piola::piolaOrderBook*, std::allocator<piola::piolaOrderBook*> > > > (__first={_M_current = 0xb277f2c4}, __last={_M_current = 0xb277f2bc},
    __result={_M_current = 0xb277f2c0})
    at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_algobase.h:358
358            return std::__copy_ni1(__first, __last, __result, __Normal());
(gdb)

这对我来说大部分是神秘的,但是在查找 memmove 时,似乎代码崩溃了,因为它无法处理向量中的删除(因为从向量中删除对于大型向量来说是一项非常繁重的操作)?

我说的对吗?如果是,我该如何解决这个问题(当然除了修复设计)?

代码在这里:

for (orderbkIterator = vOrderBook.begin(); orderbkIterator != vOrderBook.end(); orderbkIterator++)
    {

        if (  (*(*orderbkIterator)->getOrderBookId()) == *(TradableInst->getOrderBookId()) )
        {
            long long a = (*(*orderbkIterator)->getOrderBookId());
            ADDVLOG(LOG_INFO, "Removing record (%lld) from vOrderBook", a );
            vOrderBook.erase(orderbkIterator);
        } 

【问题讨论】:

  • 能贴出代码吗?
  • 真正的内存损坏可能发生在此操作附近。在valgrind 下运行您的程序并修复它报告的第一个 问题。重复直到它不抱怨为止。
  • ... 实际上现在您已经发布了代码:erase 不会使向量迭代器无效吗? (我不记得了。)
  • 每当执行 `if' 语句时,您都会增加一个无效的迭代器。
  • @Zack 废话,我认为你是对的!

标签: c++ memory-management stl crash g++


【解决方案1】:

来自std::vector::erase()

对已擦除元素以及它们与容器末端之间的元素的迭代器和引用无效。 Past-the-end 迭代器也无效。

所以如果erase() 被调用,那么orderbkIterator 将在下一次递增时无效。更改循环的结构,因为erase() 在被删除的迭代器之后返回下一个迭代器,这意味着只有在erase() 没有发生时才会增加:

for (orderbkIterator = vOrderBook.begin(); orderbkIterator != vOrderBook.end();)
{
    if (...)
    {
        orderbkIterator = vOrderBook.erase(orderbkIterator);
    }
    else
    {
        ++orderbkIterator;
    }
}

【讨论】:

    【解决方案2】:

    我很确定

    vOrderBook.erase(orderbkIterator);
    

    将使迭代器无效。继续递增会导致未定义的结果。

    【讨论】:

      【解决方案3】:

      remove erase 习惯用法将防止许多无效迭代器的陷阱。

      使用这个习语重写循环看起来像下面这样:

      vOrderBook.erase(
        std::remove_if(vOrderBook.begin(), vOrderBook.end(), <unary-predicate>),
        vOrderBook.end());
      

      一元谓词可以是 lambda 或仿函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-16
        • 2012-06-11
        • 2012-01-18
        • 1970-01-01
        • 2020-06-21
        • 1970-01-01
        相关资源
        最近更新 更多