Amo*_*tir 3 c++ stl segmentation-fault
这对我来说很奇怪,但是当我启动程序时,我遇到了意想不到的随机分段错误.有时它会工作,有时会崩溃.. Dev-C++的调试器指向我的文件行:stl_construct.h
/**
* @if maint
* Constructs an object in existing memory by invoking an allocated
* object's constructor with an initializer.
* @endif
*/
template<typename _T1, typename _T2>
inline void
_Construct(_T1* __p, const _T2& __value)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 402. wrong new expression in [some_]allocator::construct
-> ::new(static_cast<void*>(__p)) _T1(__value);
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我正在广泛使用STL ..如何检测段错误的起源?有没有可以提供帮助的工具?导致这样的随机崩溃的原因是什么?
我的程序大约有5000行代码.我不知道为了得到一些帮助我必须显示哪些代码,因为我不知道问题的根源,我从调试器得到的只是它与STL有关.
我搬到了Code::Blocks现在,这里是调用堆栈:
#0 00464635 std::_Construct<std::pair<double const, int>, std::pair<double const, int> >(__p=0xb543e8, __value=@0x10) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_construct.h:81)
#1 00462306 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_create_node(this=0x406fe50, __x=@0x10) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:367)
#2 00461DA7 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_clone_node(this=0x406fe50, __x=0x0) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:379)
#3 004625C6 std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_M_copy(this=0x406fe50, __x=0x0, __p=0x406fe54) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:1029)
#4 00462A9D std::_Rb_tree<double, std::pair<double const, int>, std::_Select1st<std::pair<double const, int> >, std::less<double>, std::allocator<std::pair<double const, int> > >::_Rb_tree(this=0x406fe50, __x=@0xb59a7c) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_tree.h:559)
#5 0045A928 std::map<double, int, std::less<double>, std::allocator<std::pair<double const, int> > >::map(this=0x406fe50, __x=@0xb59a7c) (C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/bits/stl_map.h:166)
#6 0040B7E2 VehicleManager::get_vehicles_distances(this=0xb59a50) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/VehicleManager.cpp:232)
#7 00407BDA Supervisor::IsMergeInstruction(id_vehicle=1) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/Supervisor.cpp:77)
#8 00408430 CheckingInstructionsThread(arg=0x476100) (C:/Program Files/CodeBlocks/MinGW/projects/AHS/Supervisor.cpp:264)
#9 00413950 _glfwNewThread@4() (??:??)
#10 75A24911 KERNEL32!AcquireSRWLockExclusive() (C:\Windows\system32\kernel32.dll:??)
#11 00476100 std::__ioinit() (??:??)
#12 0406FFD4 ??() (??:??)
#13 76E5E4B6 ntdll!RtlInitializeNtUserPfn() (C:\Windows\system32\ntdll.dll:??)
#14 00476100 std::__ioinit() (??:??)
#15 70266582 ??() (??:??)
#16 00000000 ??() (??:??)
Run Code Online (Sandbox Code Playgroud)
更精确一些:
1 /这是一个多线程应用程序.2 /方法:get_vehicles_distances(); 返回一张地图.3/IsMergeInstruction()调用时,地图可能不会被初始化;
显然导致段错误的行是:
vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());
Run Code Online (Sandbox Code Playgroud)
其中vehicles_distances_是Map.该行是方法的一部分:VehicleManager :: MoveAllVehicles();
void VehicleManager::MoveAllVehicles() {
vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());
vector<Vehicle>::iterator iter_end = VehicleManager::vehicles_.end();
for(vector<Vehicle>::iterator iter = VehicleManager::vehicles_.begin();
iter != iter_end; ++iter) {
(*iter).MoveVehicle();
vehicles_distances_[(*iter).get_vec_vehicle_position().y] = (*iter).get_id_vehicle();
}
}
Run Code Online (Sandbox Code Playgroud)
这有什么问题?
我试着用map :: clear(); 作为map :: erase()的替代; 但同样的问题发生了!
我想我明白了...一个线程试图利用vehicles_distances_而它被清除..(?)
问题解决了!所以它来自map :: erase(); 正如所料.我通过创建另一个映射变量来绕过问题,其中该对<key, value>被反转,因此我可以更新地图.(因为我需要的关键是距离,并且距离不是唯一的,因为它每次都会改变,但id_vehicle是唯一的!).最后我刚刚拿了那张地图,<key, value>再次将它倒置并转移到原始地图上,可以在每个循环中重新声明......
感谢大家 !
jal*_*alf 10
首先,对于所有可爱的人来说,可爱,不要使用Dev-C++.我希望我知道人们如何继续遇到那块垃圾.它没有被保持了多年,并维持情况下,也仍然是缺乏非常基本的功能垃圾的车件.放弃它,去寻找无数更好的免费替代品之一.
现在,在您的问题上:您的程序会随机发生段错误,因为您之前已经做过非法的事情.不要那样做.;)
如果你的程序在某处写出了界限,任何事情都可能发生.它可能会打到一个未分配的页面,在这种情况下,您会遇到段错误.或者它可能会在分配给您的进程的页面上查找未使用的数据,在这种情况下它将没有任何实际效果(除非之后正确初始化,覆盖您的第一次,非法,写入,然后您尝试从中读取期望原始(无效)值仍然存在.或者它可能会触及实际使用的数据,在这种情况下,当程序尝试读取该数据时,您将在以后遇到错误.
阅读数据时几乎存在相同的场景.您可以很幸运并立即获得段错误,或者您可以点击未使用和未初始化的内存,并读取垃圾数据(这很可能会在以后使用该数据时导致错误),或者您可以从内存地址读取已经在使用(这也会给你垃圾).
所以,是的,这些错误很难找到.我可以给出的最好的建议是:1)在代码中撒上断言以确保维护基本不变量,以及2)逐步完成程序,并在每一步中验证您是否正在读取或写入不满足的地址属于你.
MSVC默认启用安全SCL选项,它将对STL代码执行边界检查,这有助于发现这样的错误.
我相信GCC可以选择做类似的事情(但默认情况下没有启用).
Segfaults很讨厌.一旦人们被这样的错误咬了几次,他们往往会因为避免访问内存而变得更加自律.:)
显而易见的问题是"什么是_p".在调试器中,您应该能够查看callstack.按照_p回到原点.确认其大小正确,尚未删除,并确实存在.
如果这并不容易,那么总会有蛮力的方法来评论随机(可疑)代码,直到它工作或返回并与已知的工作副本进行区分.