-1

I have a simple question. As far as I know, if the variable scope ends, the variable is destroyed. But in the below situation, even if Derived is destroyed, the base pointer still calls the virtual function of the derived. Is it plain luck, or the Derived object will actually not be destroyed until all references/ pointers to Derived are not destroyed?

int main(int argc, char **argv) {

    Base *base_ptr;

    std::string value = "hello";

    if ( value == "hello")
    {
        Derived der1;
        base_ptr = &der1;

    }
    else {
        DerivedNew der_new;
        base_ptr = &der_new;
    }

    base_ptr->printDerived();
    // this prints the virtual function of the derived object. I was hoping it to print the base object.
}
infoclogged
  • 3,641
  • 5
  • 32
  • 53
  • related/dupe: https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – NathanOliver Mar 03 '18 at 17:01
  • C++ compiler optimized the code, and removed stupid if statement. So DerivedNew destructor not yet called. – Victor Gubin Mar 03 '18 at 17:08
  • @VictorGubin Okay, but how can I not let this happen at compile time and you mean Derived destructor not yet called? – infoclogged Mar 03 '18 at 17:13
  • Hope is not a recommended strategy. – David Schwartz Mar 03 '18 at 17:36
  • Sometimes aggressive compiler optimization like -O3 making your code working completely unexpected. In this case you can do something like #if defined( __GNUC__) && ! defined( __clang__) #pragma GCC push_options #pragma GCC optimize ("O0") #endif // __GNUC__ /* you code goes here */ #if defined( __GNUC__) && ! defined( __clang__) #pragma GCC pop_options #endif // __GNUC__ – Victor Gubin Mar 03 '18 at 18:38
  • @VictorGubin really? Compiler optimization can modify the behavior about scope and destructors? Sounds really weird to me. I agree that we are in realm of UB here, but it's not about destructor not already been called I think. A meaningful if would not change the things here – Gian Paolo Mar 03 '18 at 19:55
  • Sounds not realistic - but yes, it can. Operations reordering, alignment, dead code elimination, copy elision etc. Off cause if you have a simple code, without any tricks it will work as expected. Otherwise compiler can surprise you. – Victor Gubin Mar 03 '18 at 23:23
  • @infoclogged one more thing, from Bjarne Stroustrup. “C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.” So, if you need to avoid some "undefined behavior" simply don't write and unclear code with the tricks like making a pointer on reference on stack object. – Victor Gubin Mar 05 '18 at 10:35

2 Answers2

2

What you should have been hoping to get at that last line is a crash because your base_ptr is pointing to an object which is already destroyed since its scope has ended.

In general though this is an undefined behavior. No amount of pointers (except smart pointers) can prolong the lifetime of an object that is going out of scope.

Your code doesn't crash probably because the compiler generated the code that "allocates" a stack-frame for your function to include all objects on all paths of execution and "deallocates" it only when returning from the function. So the object is technically intact at least until the end of the function. Also whether destructor of the object is called or not is mostly irrelevant since it's not gonna make the memory where the object resides to magically disappear.

r3mus n0x
  • 5,954
  • 1
  • 13
  • 34
  • can changing the raw pointer to smart pointer make the code legal? Can you please give an example? – infoclogged Mar 03 '18 at 17:29
  • The smart pointer I was referring to is std::shared_ptr, and no, changing the regular pointer to shared_ptr in this example is not going to make this code legal because the pointed-to object is still on stack and the only way to make an object outlive its scope is to allocate it on the heap. This question, however, is about base pointer to derived object so I don't think that adding an example about smart-pointers here would be appropriate. – r3mus n0x Mar 03 '18 at 17:38
  • Thanks, it gave me a little bit of a insight nevertheless. A downvote was inappropriate seeing that I upvoted your answer. – infoclogged Mar 03 '18 at 17:43
0

You are accessing a destroyed object. That's undefined behaviour. Your program is by definition meaningless and the compiler is allowed to compile it into whatever it pleases.

It is your responsibility to not write undefined behaviour. The compiler is not required to warn you.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70