2

I'm confused about some details of wild pointer and dangling pointer, here is my code:

#include <iostream>
using std::cout;
using std::endl;

class A
{
public:
    void Func() { cout << "Func of class A, the address is:" << this <<endl; }
};

void Test(void)
{
    A *p;

    //get an error in VS2013 because of uninitialized pointer.
    //But it's ok in g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
    p->Func();     // wild pointer, ((1))

    {
        A a;
        p = &a; 
        p->Func();
    }

    p->Func();  //dangling pointer  ((2))
}

int main()
{
    Test(); 
    return 0;
}

The results are like follows:
Windows:
Func of class A, the address is:003CFD47 Func of class A, the address is:003CFD47

Ubuntu:
Func of class A, the address is:0xb74ef39d Func of class A, the address is:0xbff85a3b Func of class A, the address is:0xbff85a3b

My questions:
(1) the g++ compiler let the wile pointer pass at((1)), even when run the code, it seems point to 'some object'. why can this happen? Is it the bug of the compiler?

(2) As far as I know, after block sentences, p will be a dangling pointer at ((2)). But why can p go on point to Func()? Because the space occupied by object a is not overwrote by other application?

kkwang
  • 247
  • 2
  • 11

1 Answers1

4

p is initially uninitialized, so it contains whatever random value happened to reside on the area of the call stack that gets reserved for p. That is what you are seeing in the first cout output.

Then you create an object and assign its address to p, which you see in the second cout output.

Then the object goes out of scope and is freed, but you don't reassign anything to p, so it carries its existing value, which you see in the third cout output.

When calling an object method via an invalid pointer, although technically undefined behavior, typically nothing bad will happen as long as you do not dereference the pointer to access any members of the class, including any virtual methods that require a VMT pointer.

A method call is really just a function call with an extra hidden this parameter, so your example code is really doing the following from the compiler's perspective:

#include <iostream>
using std::cout;
using std::endl;

class A
{
public:
    static void Func(A* this) { cout.operator<<("Func of class A, the address is:").operator<<((void*)this).operator<<(&endl); }
};

void Test(void)
{
    A *p; // initialized with random value 

    A::Func(p);

    {
        A a; // note: allocates only
        A::A(&a); // then constructs
        p = &a; 
        A::Func(p);
        A::~A(&a);
    }

    A::Func(p);
}

int main()
{
    Test(); 
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770