为什么C++优化器在删除同一个指针时使用不同的delete
Why does the C++ optimizer use different delete when deleting the same pointer
当 gcc 7.3 优化我从 google 测试库中使用的一些代码时,我遇到了一个奇怪的问题。该问题已在 google 测试中得到修复,但我仍然对以下问题感到困惑:出于某种原因是否有更多具有相同签名的全局删除运算符?
我的代码在这里:https://godbolt.org/z/86Eevc 更有趣的是,对于 -O0,所有 call
指令都使用相同的删除地址。有了 -O3,一切都开始变得有趣起来。 (godbolt 上的 link 在选中“编译为二进制”时很有用,这样您就可以看到为调用参数生成的地址)。
我的 class (DeleteInside) 派生自具有虚拟 table 的 class,并具有执行 delete this;
的 deleteMe() 方法。如果我在全局范围内声明一个 DeleteInside *ptr = nullptr;
,然后在主函数中调用 delete ptr;
,删除运算符的地址与我使用 ptr->deleteMe();
时调用的删除不同。
谁能解释一下?
static int timesDeleted = 1;
class DeleteBase
{
public:
virtual ~DeleteBase() {
timesDeleted += 1;
}
};
class DeleteInside
{
int _val;
public:
~DeleteInside() {
timesDeleted = (timesDeleted * _val);
}
bool doSomething() {
return false;
}
__attribute__((noinline)) void deleteMe() const {
timesDeleted += 1;
delete this;
}
};
DeleteInside *delInside = nullptr;
int main(int argc, char *argv[]) {
//delete delInside;
delInside->deleteMe();
delete delInside;
return timesDeleted;
}
解释很简单:您调用未定义的行为(取消引用空指针),因此任何事情都可能发生。这种事情的一个 tell-tale 标志是优化级别会影响您注意到的结果。
您看到的地址在这两种情况下都是垃圾。至于它们到底为什么不同,您需要了解 GCC 7.3 如何处理这种未定义行为的特定情况的人,但对于所有意图和目的,所有有用的 C++ 解释都停留在“它是未定义的行为”。
如果非要我猜的话,vtable 及其在这种情况下的优化方式可能与此有关。
当 gcc 7.3 优化我从 google 测试库中使用的一些代码时,我遇到了一个奇怪的问题。该问题已在 google 测试中得到修复,但我仍然对以下问题感到困惑:出于某种原因是否有更多具有相同签名的全局删除运算符?
我的代码在这里:https://godbolt.org/z/86Eevc 更有趣的是,对于 -O0,所有 call
指令都使用相同的删除地址。有了 -O3,一切都开始变得有趣起来。 (godbolt 上的 link 在选中“编译为二进制”时很有用,这样您就可以看到为调用参数生成的地址)。
我的 class (DeleteInside) 派生自具有虚拟 table 的 class,并具有执行 delete this;
的 deleteMe() 方法。如果我在全局范围内声明一个 DeleteInside *ptr = nullptr;
,然后在主函数中调用 delete ptr;
,删除运算符的地址与我使用 ptr->deleteMe();
时调用的删除不同。
谁能解释一下?
static int timesDeleted = 1;
class DeleteBase
{
public:
virtual ~DeleteBase() {
timesDeleted += 1;
}
};
class DeleteInside
{
int _val;
public:
~DeleteInside() {
timesDeleted = (timesDeleted * _val);
}
bool doSomething() {
return false;
}
__attribute__((noinline)) void deleteMe() const {
timesDeleted += 1;
delete this;
}
};
DeleteInside *delInside = nullptr;
int main(int argc, char *argv[]) {
//delete delInside;
delInside->deleteMe();
delete delInside;
return timesDeleted;
}
解释很简单:您调用未定义的行为(取消引用空指针),因此任何事情都可能发生。这种事情的一个 tell-tale 标志是优化级别会影响您注意到的结果。
您看到的地址在这两种情况下都是垃圾。至于它们到底为什么不同,您需要了解 GCC 7.3 如何处理这种未定义行为的特定情况的人,但对于所有意图和目的,所有有用的 C++ 解释都停留在“它是未定义的行为”。
如果非要我猜的话,vtable 及其在这种情况下的优化方式可能与此有关。