一千萬個為什麽

搜索

C ++靜態初始化在同一個回溯中出現兩次是正常的嗎?

我正在嘗試調試用GCC編譯的C ++程序,該程序在啟動時凍結。 GCC互斥鎖保護函數的靜態局部變量,似乎等待獲取這樣的鎖是它凍結的原因。如何發生這種情況相當令人困惑。第一個模塊A的靜態初始化發生(在回溯中有__static_init函數GCC調用),它調用一個具有靜態局部變量的函數Foo()。靜態局部變量是一個對象,構造函數通過幾層函數調用,然後突然回溯有幾個??,然後它是在第二個模塊B的靜態初始化(__static函數再次發生)然後調用Foo(),但由於Foo()從未在第一次返回本地靜態變量上的互斥鎖時仍然設置,並且它會鎖定。

一個靜態init如何觸發另一個?我的第一個理論是共享庫 - 模塊A將調用模塊B中的一些函數,這將導致模塊B加載,從而觸發B的靜態初始化,但事實並非如此。模塊A根本不使用模塊B.所以我有第二個(也是可怕的)猜測。比如說:

  1. Module A uses some templated function or a function in a templated class, e.g. foo::bar()

  2. Module B also uses foo::bar()

  3. Module A doesn't depend on module B at all

  4. At link time, the linker has two instances of foo::bar(), but this is OK because template functions are marked as weak symbols...

  5. At runtime, module A calls foo::bar, and the static init of module B is triggered, even though module B doesn't depend on module A! Why? Because the linker decided to go with module B's instance of foo::bar instead of module A's instance at link time.

這種特殊情況有效嗎?或者,一個模塊的靜態init是否永遠不會在另一個模塊中觸發靜態init?

Clarification: GCC creates the mutexes automatically to guard any function static variable. I'm not doing anything with mutexes myself. It's GCC's way of making function static variables thread safe.

Update: I know that static initialization is not defined between translation units and that I shouldn't depend on an order. But I'm curious if this is normal behavior as a clue towards debugging the problem. Is it normal for a compiler to generate code that does this or is it potentially indicative of a bug in GCC?

最佳答案

Welcome to the "static initialization order fiasco". You should probably just read that entire article, as it will describe (in detail) how you may be running into this issue & how to fix it.

轉載註明原文: C ++靜態初始化在同一個回溯中出現兩次是正常的嗎?