Have a look at the following code. The goal here is to return a reference through two functions (from ReferenceProvider::getReference() to getRef() to main()):
#include <tchar.h>
#include <assert.h>
#include <string>
class BaseClass {
public:
virtual void write() const {
printf("In base class\n");
}
};
typedef BaseClass* BaseClassPointer;
class ChildClass : public BaseClass {
public:
virtual void write() const {
printf("In child class\n");
}
};
typedef ChildClass* ChildClassPointer;
//////////////////////////////////////////////////////////////////////////
ChildClass* g_somePointer = new ChildClass();
class ReferenceProvider {
public:
const BaseClassPointer& getReference() {
const BaseClassPointer& val = g_somePointer;
return val;
}
};
ReferenceProvider g_provider;
const BaseClassPointer& getRef() {
std::string test;
const BaseClassPointer& val = g_provider.getReference();
return val;
}
int _tmain(int argc, _TCHAR* argv[]) {
BaseClass* child = getRef();
assert(child == g_somePointer);
child->write();
return 0;
}
Now, when debugging this code (in Visual C++), breaking at return val; in getRef() will give you a screen like this:

Notice how the values of g_somePointer and val are the same. Now, step over the return statement and you’ll get a screen like this:

Notice how val has become invalid (0xcccccccc). This is probably because the stack of getRef() has been cleared and val is no longer available.
The problem now is that child in _tmain() will get this invalid value (0xcccccccc) rendering child unusable. So my first (and main) question is: How to do this correctly?
(Please note that this is just an boiled down example from some other code I’ve been working on. It needs to be structured like with, including using references to pointers.)
What’s making this whole thing very strange (and hard to debug) is that the function getRef() works under some conditions:
- If you change the type of
g_somePointertoBaseClass*(fromChildClass*) - If you remove the local variable in
getRef()(i.e. the linestd::string test;)
In both cases the reference variable val (in getRef()) will not become invalid and the function will return the correct pointer address. Can anybody explain this to me?
The problem is here:
Since
g_somePointerhas a different type (ChildClass*is convertible toBaseClass*, but is not the same type),valcannot refer directly tog_somePointer. Instead, a temporary copy is made, converted to the correct type, andvalrefers to that.The temporary only lasts as long as
val, going out of scope at the end of the function, so the function returns an invalid reference.In that case, no pointer conversion is required, and so
valcan refer directly tog_somePointer. The code is then correct, but fragile.With the string variable, there is a destructor call at the end of the function, which overwrites the defunct stack frame that contains the temporary pointer. Without it, nothing overwrites the memory, so the code appears to work – which is unfortunate, as it makes the error much harder to notice.