【问题标题】:What are the possible reasons for signal 11 on destructor call?析构函数调用中信号 11 的可能原因是什么?
【发布时间】:2013-02-18 12:19:13
【问题描述】:

我有以下循环(当使用 delete[] 删除 SgApp 类型的 24 个对象的数组时会发生这种情况)

   0x086f5361 <+45>:    cmp    ebx,DWORD PTR [esi+0x4]
   0x086f5364 <+48>:    je     0x86f5375 <PSM::~PSM()+65>
   0x086f5366 <+50>:    sub    ebx,0xd4
   0x086f536c <+56>:    mov    eax,DWORD PTR [ebx]
   0x086f536e <+58>:    mov    DWORD PTR [esp],ebx
=> 0x086f5371 <+61>:    call   DWORD PTR [eax]
   0x086f5373 <+63>:    jmp    0x86f5361 <PSM::~PSM()+45>

在这段代码中,%ebx 就像一个迭代器,%esi 指向数组的开头,sizeof(SgApp)=0xd4。在数组的开头,前 4 个字节代表数字 24。 0x086f5371 &lt;+61&gt;: call DWORD PTR [eax] 行调用 SgApp 默认的虚拟析构函数。

  1. 从这段代码中,我了解到对象的第一个 DWORD 指向一个 vtable,而 vtable 中的第一个 DWORD 指向析构函数。它是否正确?每次我有一个虚拟析构函数时都会发生这种情况?

  2. 在什么情况下调用析构函数会导致信号 11 段错误在该行 0x086f5371 &lt;+61&gt;: call DWORD PTR [eax]?我的猜测是 %eax 指向的值在某个未分配的区域中,但可能的原因是什么?此时我应该拥有所有 24 个 SgApp 类型的对象(它们是在构造函数中创建的)。

我提到这个信号 11 只发生了一次,我得到的只是一个糟糕的核心转储。在正常情况下,这是不可重现的,所以我正在寻找所有可能的解释,包括可能是一些硬件故障或一些奇异的场景。

【问题讨论】:

  • 你不能显示实际的 C++ 代码吗?
  • @JoachimPileborg 不幸的是,我不能,但基本上在 PSM 构造函数中我有 keys = new SgApp[24]; 并且在 PSM 析构函数中我有 delete [] keys; 。也没有 PSM 对象作为值传递。
  • 可能是您正在删除一个实际上并不存在的对象,因此this 很可能是 null 或析构函数中的另一个无效指针。
  • 复制构造函数和赋值运算符长什么样子?是否还有其他代码可以修改keys 成员变量或将其公开给类用户?
  • @TadeuszKopec 确实没有实现复制构造函数和赋值运算符(这不是我的设计,在代码中所有参数都不是按值传递的,而只是指针传递),但这不是原因。如果在前 4 个字节之前要删除的键不代表 24,而是使用 gcc 编译器的 -1。

标签: c++ assembly g++ segmentation-fault coredump


【解决方案1】:

我推测你没有关注rule of three,你最终会得到两个或更多指向同一个动态分配数组的对象。当他们的析构函数被调用时,第二次调用会导致尝试delete [] 一些已经被delete[]ed 的东西。

【讨论】:

  • 确实没有实现复制构造函数和赋值运算符(这不是我的设计,在代码中所有参数都不是按值传递,而只是指针传递),但这不是原因。如果 keys 在前 4 个字节之前要删除的位置将不代表 24,而是使用 gcc 编译器的 -1。编辑:我有一个核心转储,我可以打印一些值,包括数组的前 4 个字节。
猜你喜欢
  • 1970-01-01
  • 2017-02-06
  • 2017-11-10
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 2013-02-16
  • 2021-09-01
  • 2012-01-01
相关资源
最近更新 更多