有正就有反, 有男就有女, 有前就有後, 東西南北, 凸與凹, 扯太多了, 有建構函式必有解構函式, 接續 ctor 的議題:
_GLOBAL__I_io call
_Z41__static_initialization_and_destruction_0ii
_Z41__static_initialization_and_destruction_0ii 除了呼叫 ctor 之外, 還為 dtor 做了準備。g++ 使用 __cxa_atexit 來註冊每一個 dtor, 所以 _Z41__static_initialization_and_destruction_0ii 還呼叫了 __cxa_atexit。
14 1df: 66 b8 3c 03 00 00 mov $0x33c,%eax
15 1e5: 67 66 c7 44 24 08 6c addr32 movl $0x106c,0x8(%esp)
16 1ec: 10 00 00
17 1ef: 67 66 c7 44 24 04 60 addr32 movl $0x1060,0x4(%esp)
18 1f6: 10 00 00
19 1f9: 67 66 89 04 24 addr32 mov %eax,(%esp)
20 1fe: 66 e8 84 ff ff ff calll 188 <__cxa_atexit>
__cxa_atexit function prototype:
int __cxa_atexit(void (*destructor) (void *), void *arg, void *__dso_handle)
- L14, 0x33c 就是 <_ZN2IoD1Ev> (Io 的 destructor),
- L17, $0x1060 則是 global io object 的位址 (in .bss section, use readelf -a cppb.elf to see), Io::~Io() 要把自己傳進去, 就是 this 指標, 所以會需要這個參數。
- L15, $0x106c 自然是 __dso_handle。
因為有兩個 dtor, 所以 __cxa_atexit 呼叫了兩次。
再來就是在 __cxa_atexit 裡頭把應該要存的東西存起來, 在適當的時候呼叫他們 (ex: 離開 c++ main()), 就完成解構了。
什麼是要存的東西?
- dtor
- dtor argument (this pointer)
- __dso_handle
這是兩種 dtor 的實作方式之一, 另外一種 g++ 新版已經不用了, 就是使用 .dtor section 來儲存每個 dtor function, 類似 ctor section, 然後一個一個 call 他們就好了, 說來簡單, 不過可能實際上的實作並不容易, 才會改用這種方式。
以上的 objdump 結果來自下面的程式碼。
ref:
http://hilananufi.serw5.com/global-object-destructor-c.php
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。