my_list.push_back() 时分配错误

Bad allocation error when my_list.push_back()

我正在尝试控制我正在开发的程序的工作流程。为此,我有一个 map< unsigned int, list < unsigned int > >,其中第一个键是 id,第二个键(列表)将用于了解我是否正确结束了所有任务。我在此列表中使用的唯一操作是:

myMap[iD].size()
myMap[iD].push_back(foo) <- ( foo is an unsigned int )
for (std::list<unsigned int>::iterator it=myMap[iD].begin(); it != myMap[iD].end(); ++it){
myMap[iD].erase(it)
}

我的地图的长度可以增长到 1452 个元素,每个元素列表大小可以从 1000 到 5000 的数量级。

当我 运行 程序有时会收到分段错误,有时会收到错误的分配错误。我的猜测是这来自 push_back 因为:

这是我使用地图的唯一代码部分:

if (FOO != 0){
    if (PID != 0){

        if ( myMap.size() + 5 < myMap.max_size()){
            if (myMap[PID].size() > 1000) myMap[PID].pop_front();
            myMap[PID].push_back(EVENTVALUE);
        }

    }
} else {
    if (PID != 0 and foo2 != 0 and myMap.find(PID) != myMap.end()) {
        for (std::list<unsigned int>::iterator it=myMap[PID].begin(); it != myMap[PID].end(); ++it){
            if (*it == foo2){
                cout << " erasing pid: " << PID <<  endl;
                myMap[PID].erase(it);
                if ( myMap[PID].size() == 0 ) myMap.erase(PID);
                break;
            }

        }
    }
}

我也尝试过使用工具 Valgrind,这是输出:

==4092== Invalid read of size 8
==4092==    at 0x4F09EB8: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib64/libstdc++.so.6.0.21)
==4092==    by 0x40CCA9: construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (new_allocator.h:120)
==4092==    by 0x40CCA9: _S_construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (alloc_traits.h:254)
==4092==    by 0x40CCA9: construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (alloc_traits.h:393)
==4092==    by 0x40CCA9: std::vector<std::string, std::allocator<std::string> >::push_back(std::string const&) (stl_vector.h:905)
==4092==    by 0x4157AC: foo::foo(std::basic_ofstream<char, std::char_traits<char> >&) (foo.cc:1743)
==4092==    by 0x404F49: main (foo.cc:3159)
==4092==  Address 0x6157d08 is 0 bytes after a block of size 8 alloc'd
==4092==    at 0x4C29670: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==4092==    by 0x40DB77: allocate (new_allocator.h:104)
==4092==    by 0x40DB77: _M_allocate (stl_vector.h:168)
==4092==    by 0x40DB77: void std::vector<std::string, std::allocator<std::string> >::_M_emplace_back_aux<std::string>(std::string&&) (vector.tcc:404)
==4092==    by 0x408F3E: push_back (stl_vector.h:920)
==4092==    by 0x408F3E: split(std::string const&, char, int) (foo.cc:416)
==4092==    by 0x41577F: lustreLine::toPRV(std::basic_ofstream<char, std::char_traits<char> >&) (foo.cc:1741)
==4092==    by 0x404F49: main (foo.cc:3159)
==4092== 
==4092== Invalid read of size 4
==4092==    at 0x4F09EBB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib64/libstdc++.so.6.0.21)
==4092==    by 0x40CCA9: construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (new_allocator.h:120)
==4092==    by 0x40CCA9: _S_construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (alloc_traits.h:254)
==4092==    by 0x40CCA9: construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (alloc_traits.h:393)
==4092==    by 0x40CCA9: std::vector<std::string, std::allocator<std::string> >::push_back(std::string const&) (stl_vector.h:905)
==4092==    by 0x4157AC: foo::foo(std::basic_ofstream<char, std::char_traits<char> >&) (foo.cc:1743)
==4092==    by 0x404F49: main (foo.cc:3159)
==4092==  Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd
==4092== 
==4092== 
==4092== Process terminating with default action of signal 11 (SIGSEGV)
==4092==  Access not within mapped region at address 0xFFFFFFFFFFFFFFF8
==4092==    at 0x4F09EBB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib64/libstdc++.so.6.0.21)
==4092==    by 0x40CCA9: construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (new_allocator.h:120)
==4092==    by 0x40CCA9: _S_construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (alloc_traits.h:254)
==4092==    by 0x40CCA9: construct<std::basic_string<char>, const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&> (alloc_traits.h:393)
==4092==    by 0x40CCA9: std::vector<std::string, std::allocator<std::string> >::push_back(std::string const&) (stl_vector.h:905)
==4092==    by 0x4157AC: foo::foo(std::basic_ofstream<char, std::char_traits<char> >&) (fpp.cc:1743)
==4092==    by 0x404F49: main (foo.cc:3159)
==4092==  If you believe this happened as a result of a stack
==4092==  overflow in your program's main thread (unlikely but
==4092==  possible), you can try to increase the size of the
==4092==  main thread stack using the --main-stacksize= flag.
==4092==  The main thread stack size used in this run was 8388608.

[...]

(如果需要更多输出,请询问)

出于隐私考虑,我不得不更改一些变量名称,希望这不是问题。

感谢阅读,祝您有愉快的一天!

第一个for循环是错误的:

for (std::list<unsigned int>::iterator it=myMap[iD].begin(); it != myMap[iD].end(); ++it){
    myMap[iD].erase(it);
}

因为迭代器it在每次调用erase后失效。

您可以将其重写为:

for (auto it = myMap[iD].begin(); it != myMap[iD].end(); )
{
    it = myMap[iD].erase(it);
}

或更好只是

myMap[iD].clear();

您的问题中似乎还有其他 for 循环,您犯了类似的错误 - 通常您需要使用模式:

for (auto it = foo.begin(); it != foo.end(); )
{
    if (some_condition)
        it = foo.erase(it);   // erase map entry, update iterator
    else
        ++it;                 // bump iterator
}

参见 cppreference.com entry for std::map::erase 上的示例。