Petr
Petr

Reputation: 21

C++ : unallocated pointer to object can be repeatedly safely dereferenced... why?

why is this code practically reliably working, is not unstable, undefined? it's dereferencing unallocated, dangling pointers to objects. thanks.

#include <iostream>
using namespace std;

class Base{
    public:
    void vf()
    {
        cout<<"vf\n";
    }
    void pr(){
        cout<<"vb\n";
    }
};

int main() {
    Base* b ;

    //Base * bp = new Base;   //trying to disrupt memory
    char ar[]= "ttttttttttt"; //trying to disrupt memory

    b->pr();
    char aa[]= "ttttttttttt";
    b->vf();
    return 0;
}

Upvotes: 0

Views: 364

Answers (1)

templatetypedef
templatetypedef

Reputation: 372724

Welcome to the Wonderful World of Undefined Behavior! According to the C++ spec, the behavior of this problem is undefined, so what you're seeing might work on your system but crash on others, or vice-versa.

Practically speaking, what's happening here is probably an artifact of how the compiler generates code for member functions. Typically, a member function that looks like this:

void doSomething() {
    cout << "Hello!" << endl;
}

would probably be compiled as if it were a free function like this:

void Base_doSomething(Base* this) {
    cout << "Hello!" << endl;
}

In that sense, when you write

bf->doSomething();

the compiler treats it as if you've written

Base_doSomething(bf);

and nothing bad happens, because Base_doSomething doesn't reference the this pointer, which is where all the bad things happen.

Now, this is very brittle. If you try to read any of the data members of the Base type, this code will crash because then you are reading from a bad pointer. Similarly, if doSomething were a virtual function, you'd get a crash because calling a virtual function (typically) requires reading from the receiver object to find the vtable to determine which function to call, and a dangling pointer will then lead to a bad memory access.

So, to summarize:

  • This code leads to undefined behavior, so the particular behavior you're seeing isn't guaranteed to happen or work across platforms.
  • Although syntactically bp->doSomething() looks like a pointer dereference, it might not actually involve a pointer dereference.
  • Member functions are typically compiled as free functions that have an "implicit this" pointer passed as a first argument.
  • Virtual functions work differently than this, so you'd expect to see different behavior there.

Hope this helps!

Upvotes: 4

Related Questions