我正在尝试控制正在开发的程序的工作流程。为此,我有一个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.
[...]
(如果需要更多输出,请询问)
我不得不为隐私更改一些变量名称,希望这不是问题。
感谢您阅读并度过美好的一天!
答案 0 :(得分:7)
第一个for
循环错误:
for (std::list<unsigned int>::iterator it=myMap[iD].begin(); it != myMap[iD].end(); ++it){
myMap[iD].erase(it);
}
因为每次调用erase
后迭代器it
都会失效。
您可以将其重写为:
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
}