简体   繁体   中英

Why does the C++ optimizer use different delete when deleting the same pointer

I've come accross a strange issue when gcc 7.3 optimizes some code I'm using from the google test library. The issue's been fixed in google test but I'm still puzzled by the question: are there more global delete operators with the same signature for some reason?

My code is here: https://godbolt.org/z/86Eevc and what's more interesting is that with -O0 the same delete address is used with all the call instructions. It's with -O3 that everything starts getting interesting. (The link on godbolt is useful with "Compile to binary" checked so that you can see the addresses generated for the call arguments).

My class (DeleteInside) derives from a class that has a virtual table, and has a deleteMe() method that does delete this; . If I declare a DeleteInside *ptr = nullptr; at global scope and then call delete ptr; in the main function the address of the delete operator is different than the delete that is called when I use ptr->deleteMe(); . Can anyone explain?

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;
}

The explanation is simple: you invoke undefined behaviour (dereferencing a null pointer) and thus anything can happen. A tell-tale sign for this kind of thing is that optimization level influences the result as you note.

The address you are seeing is rubbish in both cases. As to why exactly they are different, you'll need someone with knowledge of how GCC 7.3 handles this specific case of undefined behaviour, but for all intents and purposes, all useful C++ explanations stop at "it's undefined behaviour".

If I had to guess, the vtable and how it is optimized away in this case may have something to do with it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM