C++ 为什么我会随机得到错误?

C++ 为什么我会随机得到错误?,c++,stl,segmentation-fault,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

这对我来说很奇怪,但当我启动我的程序时,我遇到了一个意外的随机分段错误。有时它能工作,有时它会崩溃。。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);
    }
还有一些精度:

1/它是一个多线程应用程序。 2/方法:获取车辆距离();返回一个映射。 3/当IsMergeInstruction()调用映射时,它可能没有初始化

编辑: 显然,导致SEG故障的线路是:

vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());
地图上显示了车辆的位置。此行是方法的一部分:VehicleManager::MoveAllVehicles()

void VehicleManager::MoveAllVehicles(){
车辆距离擦除(车辆距离开始(),车辆距离结束());
vector::iterator iter_end=VehicleManager::vehicles_u.end();
对于(vector::iterator iter=VehicleManager::vehicles_uz.begin();
国际热核聚变实验堆!=国际热核聚变实验堆结束;++iter){
(*iter.movevevehicle();
车辆距离获取车辆位置获取车辆id获取车辆位置;
}
}
这有什么不对

编辑: 我尝试使用map::clear();作为对map::erase()的替换;但同样的问题也发生了

编辑: 我想我明白了。。。当线程被清除时,它试图利用车辆。。(?)

编辑: 问题解决了!所以它来自map::erase();正如所料。我绕过了这个问题,创建了另一个映射变量,其中对
被反转,因此我可以更新映射。(因为我需要的关键是距离,距离不是唯一的,因为它每次都在变化,但id_车辆是唯一的!)。最后,我只是拿了那张地图,再次反转
,并将其转移到原始地图,可以在每个循环中重新声明


谢谢大家

你可以试着找到问题所在。考虑到你在问题中的那一行,我不得不猜测你要么破坏了堆,要么是堆栈问题。

这是非常模糊的,所以几乎不可能回答。一个明显的建议是检查是否初始化了所有变量。有些编译器会在调试时将未初始化的内容归零,而在发行版中不会这样做,例如,这会导致随机和意外的结果。

调试器应该允许您进入调用堆栈。通过这种方式,您应该能够在自己的代码中看到导致seg故障的位置。

显而易见的问题是“什么是。在调试器中,您应该能够查看调用堆栈。跟随p回到它的原点。确认它的大小正确,没有被删除,并且它确实存在


如果这不容易,那么总会有蛮力方法注释掉随机(可疑)代码,直到它工作为止,或者返回并与已知的工作副本进行扩散。

在使用核心文件运行调试器后,堆栈跟踪告诉您什么? 以正常方式运行gdb gdb a.out

然后检查核心文件

核心

再看一看堆栈

英国电信


首先,出于对所有可爱事物的热爱,不要使用Dev-C++。我希望我知道人们是如何不断地撞上那块垃圾的。它已经好几年没有维护了,即使在维护的时候,它仍然是一个有缺陷的垃圾,缺乏非常基本的功能。放弃它,去寻找无数更好的免费选择

现在,请回答您的问题:您的程序会随机出现故障,因为您之前做了一些非法的事情。不要那样做

如果您的程序在某个地方写得越界,任何事情都可能发生。它可能会碰到一个未分配的页面,在这种情况下,您会得到一个segfault。或者,它可能会命中分配给进程的页面上未使用的数据,在这种情况下,它不会产生任何实际效果(除非它在之后正确初始化,覆盖您的第一个非法写入,然后您尝试从中读取,期望原始数据(无效)值仍然存在。或者它可能会命中实际使用的数据,在这种情况下,当程序尝试读取该数据时,您将在稍后收到错误

在读取数据时也存在着几乎相同的情况。你可以幸运地立即得到一个SEGFULT,或者你可以点击未使用和未初始化的内存,然后读取垃圾数据(这很可能会在以后使用该数据时导致错误),或者你可以从已经在使用的内存地址中读取(这也会给你带来垃圾)

因此,是的,这些错误很难发现。我能给出的最好建议是:1)在代码中散布断言,以确保基本不变量得到维护;2)逐步完成程序,并在每一步中,验证您没有读取或写入不属于您的地址

MSVC有一个默认启用的安全SCL选项,该选项将对STL代码执行边界检查,这有助于发现这样的错误

我相信GCC也可以做类似的事情(但默认情况下不启用)


断层很严重。一旦人们被这样的错误咬了几次,他们就会变得更加自律,避免访问超出范围的内存。:)

这很可能与无效迭代器有关-搜索在容器上迭代的位置和/或将迭代器保留在容器中,同时删除/插入元素。
正如其他人所指出的,使用调用堆栈来找到确切的位置。

您可以在程序开始时使用它来启用一些堆调试选项。另见。这可能会帮助你找到你在哪里用记忆做坏事。它在Microsoft的C运行时中可用,默认情况下,您可以使用MinGW编译器链接它。如果您使用的是GNU的C运行时,那么您将无法执行此路线。

问题更可能出现在
vehicles_distances_.erase(vehicles_distances_.begin(), vehicles_distances_.end());
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();

     }

}
template<typename _T1, typename _T2>
    inline void
    _Construct(_T1** __p, const _T2& __value)
    {

       ::new(static_cast<void*>(*__p)) _T1(__value);
    }
template<typename _T1, typename _T2>
    inline void
    _Construct(_T1*& __p, const _T2& __value)
    {

       ::new(static_cast<void*>(__p)) _T1(__value);
    }
 fprintf(stderr, "main() entered\n");