GCC 6.1.0 分段错误 - GCC 错误

  • 本文关键字:GCC 错误 分段 c++ gcc gcc6
  • 更新时间 :
  • 英文 :


让我们考虑一下下面的代码。事实上,这是我使用 gmock 和模拟 void(void) 方法发现的缩小问题。

class Base {
 public:
  virtual ~Base() {}
};
class Derived : public Base
{
 public:
  void GetValueAndDelete()  { delete this; } //here we crash
};
int main() {
  Derived* p = 0;
  p->GetValueAndDelete();
}

构建它:

/tools/gcc6.1/bin/g++ --version
g++ (GCC) 6.1.0

优化级别不同于 -O0 且运行结果会导致分段错误。

是 gcc 错误还是带有 c++ 代码的东西(是的,是的,我知道它使用副作用,但它适用于其他编译器并且无需优化)

是 gcc 错误吗

不。

或带有 C++ 代码的内容

是的。在不指向有效对象的指针上使用箭头运算符。这具有未定义的行为。

取消引用空指针并以这种不使用任何成员的方式调用方法是可以的。

按照标准是不的。是UB。

什么是指针上的调用方法?

是特定于实现的。

删除它没什么特别的。

删除this是非常特别的。

您应该只注意在之后不使用任何成员

是的,您必须确保仅使用new来创建调用该函数的所有实例。没有自动对象,没有静态对象没有new[],没有malloc+放置新。

所以是的,你可以delete this,但要小心。

你在这里的直觉似乎是:

  1. p->是可以的,因为它只是填写this的语法。
  2. delete this是可以的,因为您在delete之后不使用this

但上述内容实际上可能并不正常,因为取消引用空指针始终是未定义的行为。 如果没有启用优化,这可能不会造成任何麻烦,因为编译器正在执行"基本编译",这与您"在脑海中编译"时的想象有些匹配。 然而,通过优化,GCC会做很多它通常不会做的事情,比如在面对不正确的源代码时不费心发出"正确"的指令。 当你说p->是程序的第一个行为时,它根本不需要做任何事情——它可以假装main()是空的(或者崩溃,就像你的情况一样)。

我知道在 nullptr 上调用方法不符合标准,但到目前为止,我还没有看到一个编译器无法以描述的方式处理这个问题。似乎 gcc6.1 的工作方式不同(仍然根据规范)。所以这是gmock错误。我想知道有多少其他项目依赖于这种编译器行为:)

值得一提的是,该方法被调用,"this"内部按预期为零,然后删除失败。我查看了程序集,其中有 mov (%rax),%rbx,它失败了,因为 rax 包含零。

相关内容

  • 没有找到相关文章

最新更新