Note that there are some explanatory texts on larger screens.

plurals
  1. POStrange C++ reference invalidation on return
    primarykey
    data
    text
    <p>Have a look at the following code. The goal here is to return a reference through two functions (from <code>ReferenceProvider::getReference()</code> to <code>getRef()</code> to <code>main()</code>):</p> <pre><code>#include &lt;tchar.h&gt; #include &lt;assert.h&gt; #include &lt;string&gt; 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&amp; getReference() { const BaseClassPointer&amp; val = g_somePointer; return val; } }; ReferenceProvider g_provider; const BaseClassPointer&amp; getRef() { std::string test; const BaseClassPointer&amp; val = g_provider.getReference(); return val; } int _tmain(int argc, _TCHAR* argv[]) { BaseClass* child = getRef(); assert(child == g_somePointer); child-&gt;write(); return 0; } </code></pre> <p>Now, when debugging this code (in Visual C++), breaking at <code>return val;</code> in <code>getRef()</code> will give you a screen like this:</p> <p><img src="https://i.stack.imgur.com/5YZNQ.png" alt="Breaking a return"></p> <p>Notice how the values of <code>g_somePointer</code> and <code>val</code> are the same. Now, step over the return statement and you'll get a screen like this:</p> <p><img src="https://i.stack.imgur.com/bTAKU.png" alt="Breaking after return"></p> <p>Notice how <code>val</code> has become invalid (<code>0xcccccccc</code>). This is probably because the stack of <code>getRef()</code> has been cleared and <code>val</code> is no longer available. </p> <p>The problem now is that <code>child</code> in <code>_tmain()</code> will get this invalid value (<code>0xcccccccc</code>) rendering <code>child</code> unusable. So my first (and main) question is: <em>How to do this correctly?</em> </p> <p>(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.)</p> <p>What's making this whole thing very strange (and hard to debug) is that the function <code>getRef()</code> works under some conditions:</p> <ol> <li>If you change the type of <code>g_somePointer</code> to <code>BaseClass*</code> (from <code>ChildClass*</code>)</li> <li>If you remove the local variable in <code>getRef()</code> (i.e. the line <code>std::string test;</code>)</li> </ol> <p>In both cases the reference variable <code>val</code> (in <code>getRef()</code>) will <em>not</em> become invalid and the function will return the correct pointer address. Can anybody explain this to me?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload