为什么我会随机出现段错误?

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很讨厌.一旦人们被这样的错误咬了几次,他们往往会因为避免访问内存而变得更加自律.:)


Mic*_*hne 6

您可以尝试Valgrind来帮助找到问题.考虑到你在问题中提出的问题,我不得不猜测你已经破坏了堆,或者你有堆栈问题.


Dou*_* T. 6

显而易见的问题是"什么是_p".在调试器中,您应该能够查看callstack.按照_p回到原点.确认其大小正确,尚未删除,并确实存在.

如果这并不容易,那么总会有蛮力的方法来评论随机(可疑)代码,直到它工作或返回并与已知的工作副本进行区分.