c++memory-management

Why does this work? C++ memory management


Possible Duplicate:
Why is the below piece of code is not crashing, though I have deleted the object?

Today, I found out that I know nothing about C++ memory management. Please take a look at this piece of code:

class A
{
    public:
        A(){std::cout << "constructor called" << this << std::endl;}
        ~A(){std::cout << "destructor called" << this << std::endl;}
        void test (){std::cout << "test" << this << std::endl;}
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    A *aa = new A();

    delete aa;
    aa->test();
    aa->test();
    aa->test();
    std::cout << "still works\n";
    return a.exec();
}

Why doesn't it crash? Why does it still continue executing, despite the destructor was called? When I call the test method, I deal with memory that doesn't belong to the application any more.

What is more surprising is it still works even if I insert aa = NULL; right after delete aa;. The test method gets called all right. I need to confess that I'm totally confused. What is the purpose of destructors and assigning NULL if it doesn't have any effect?


Solution

  • Why does this work?

    There are two ways to answer your question:

    Technical Answer:

    Your code has an undefined behavior (UB).

    It dereferences a NULL or a deleteed pointer. As per the C++ standard both invoke undefined behavior. Whether it works or not is pointless.

    Undefined behavior means that any behavior is possible, and it may or may not crash, but it means that your program cannot be expected to give any well-defined output. It simply means that any behavior is possible and it may not be consistent or well defined.

    Practical Answer:

    It doesn't crash because the compiler does not actually dereference this while calling member function. Unless the function is an virtual function, the compiler converts the member function call to a usual function call by passing this as the first parameter to the function. It can do so, because the compiler can exactly determine which function to call at compile time itself. So practically, calling the member function through deleted or NULL pointer does not dereference the this(which is invalid if its NULL or deleteed). Further, the this is dereferenced only if any member is accessed inside the function body.

    In your case, you never access any member inside the function body and hence it does not crash. Add a member and dereference it inside your function and it should definitely crash.

    Regardless of what is said in a practical answer, the technical answer is above and over everything since the standard says that.