Where is an abandoned object in C ++?

I want to find out where my abandoned object is stored in memory. So I wrote a tiny program for him:

#include <iostream> #define print_dist() int a;\ do { std::cout << __FUNCTION__ << "() a[" << (long)&a - (long)ptrMainStackBase << "]" << std::endl; } while (0) #define print_distx(x) \ do { std::cout << __FUNCTION__ << "() " #x "[" << (long)&x - (long)ptrMainStackBase << "]" << std::endl; } while (0) #define print_distxy(x, y) \ do { std::cout << __FUNCTION__ << "() " #x "(ex)[" << (long)&x - (long)y << "]" << std::endl; } while (0) class CTest { public: CTest() { std::cout << "CTest::CTest" << std::endl; } // private: CTest(const CTest&) { std::cout << "copy" << std::endl; } }; const CTest *ptrException; int *ptrMainStackBase; void Test2() { print_dist(); CTest test; print_distx(test); std::cout << "&test=" << &test << std::endl; throw test; } void Test1() { print_dist(); try { Test2(); } catch (const CTest& test) { ptrException = &test; print_dist(); print_distx(test); print_distxy(test, ptrException); std::cout << "&test=" << &test << std::endl; throw test; } } int main() { int b; ptrMainStackBase = &b; print_dist(); try { print_dist(); Test1(); } catch (const CTest& test) { print_dist(); print_distx(test); print_distxy(test, ptrException); std::cout << "&test=" << &test << std::endl; } return 0; } 

and he prints:

 main() a[-4] main() a[-8] Test1() a[-64] Test2() a[-104] CTest::CTest Test2() test[-108] &test=0x7fffd3b21628 <- test created here on stack copy Test1() a[-68] Test1() test[-140736732956164] Test1() test(ex)[0] &test=0xb89090 <- and copied here copy main() a[-12] main() test[-140736732956020] main() test(ex)[144] &test=0xb89120 <- and here 

It seems that when I drop the object, it is first copied to another stack, which is far from the usual one. It's true? And why is there a 144-byte distance between two "exception stack frames"?

+7
source share
2 answers

When you drop an object, it really copies first to a temporary place. Otherwise, expanding the stack would take it out of scope. Catching it then by reference would lead to undefined behavior, for example:

 void foo() { A a; throw a; } void bar() { try { foo(); } catch (A& a) { // use a } } 

If a not copied to any temporary location, you will have a reference to a variable that no longer exists in catch . For this to work, a must have an open copy constructor (if you are not using VS, in this case it will also use private ... ). Also, this is a good reason to catch the link - otherwise you will have two copies, not one.

+6
source

It seems that when I drop the object, it is first copied to another stack, which is far from the usual one. It's true?

The thrown test does not exist when the exception is caught. This original test has already been destroyed. Thus, it must be a copy, and the new object is managed separately from the arguments and local variables. In other words, not on the stack.

Where does he live? This is before implementation. Most likely, this is dynamic memory (for example, a bunch), which the implementation implements for you.

And why is there a 144-byte distance between two “exception stack frames”?

The standard does not say how an implementation should handle an exception when it is re-selected in a catch . Since throw local variable must necessarily make a copy, the easiest way to implement throw is to always make a copy.

+2
source

All Articles