让我们考虑以下代码。事实上,这是我使用gmock和mocking 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 bug还是带有c ++代码的东西(是的,是的,我知道它使用副作用,但它可以与其他编译器一起使用,也没有优化)
答案 0 :(得分:4)
是gcc bug
没有
或带有c ++代码的东西
是。您可以在不指向有效对象的指针上使用箭头运算符。这有不明确的行为。
以这种不使用任何成员的方式解除引用空指针和调用方法很好。
根据标准,它不是罚款。它的UB。
什么是指针调用方法?
具体是实施。
删除这个并不特别。
删除this
非常特别。
在
之后,你应该只照顾不使用任何会员
是的,和必须确保仅使用new
来创建调用该函数的所有实例。没有自动对象,没有静态对象new[]
,没有malloc
+展示位置。
是的,你可以 delete this
,但要小心。
答案 1 :(得分:2)
你的直觉似乎是:
p->
没问题,因为它只是填写this
的语法。delete this
没问题,因为您在this
之后没有使用delete
。但上面可能实际上并不行,因为取消引用空指针总是未定义的行为。如果没有启用优化,这可能不会造成任何麻烦,因为编译器正在进行基本编译"当你在脑海里编译时,这有点与你想象的相符。"然而,通过优化,GCC将做很多通常不会做的事情,比如不打扰发出"纠正"面对不正确的源代码时的说明。当你说p->
作为你的节目的第一幕时,根本不需要做任何事情 - 它可能只是假装main()
是空的(或者崩溃,如同在你的情况下)。
答案 2 :(得分:0)
我知道nullptr上的调用方法是不合标准的,但到目前为止,我还没有看到编译器无法用所描述的方式处理它。似乎gcc6.1的工作方式不同(仍然按照规范)。所以这是gmock bug。我想知道有多少其他项目依赖于这种编译器行为:)
值得一提的是,该方法被称为“这个方法”。内部按预期为零,然后删除失败。我查看了程序集中有一个mov(%rax),%rbx因为rax包含零而失败。