一段程序在gcc 5.4下編譯後,執行發生段錯誤,在gcc 4.4.7下編譯後,執行正常,什麼原因?
是編譯器的問題,還是附帶的STL庫的問題?
#include &
#include &std::vector&
b(3); static void init_global() __attribute__ ((constructor));
void init_global()
{
b[0] = 1;
}int main()
{
std::cout &<&< b[0] &<&< std::endl; return 0; }
#include &
#include &
static std::vector&
static std::vector&
static bool init = false;
if(!init) {
b[0] = 1;
init = true;
}
return b;
}
int main()
{
std::cout &<&< getB()[0] &<&< std::endl;
return 0;
}
為什麼一定要依賴 __attribute__((constructor)) 這種不確定的東西。如果上面的方法能解決,何必依賴連接器的初始化代碼的順序。
__attribute__((constructor)) 不是不能用,用的時候一定自己想好,每個模塊之間的初始化順序是不確定的,看連接器的參數傳遞。我懷疑是因為c++標準和gcc標準對於全局變數初始化和constructor的調用的順序沒有規範導致的。可能在兩個gcc版本中順序變了,具體可以用下面的代碼測試一下。
struct Foo { Foo() { printf("foo
"); } };
__attribute__((constructor)) static void _bar() { printf("bar
"); }
來源:
http://stackoverflow.com/questions/8433484/c-static-initialization-vs-attribute-constructor為什麼要寫這樣的代碼呢?
試著用 MinGW GCC 6.2.0 編譯題主給的這段代碼,跑起來沒問題,放 Linux (GCC 4.8.4) 上編譯運行就 Segment Fault 了。
@董昊 的答案應該是正解,gdb 調試是這樣的:
GCC 4.8.4:
...
(gdb) r
Starting program: /home/andy/a.out
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a30 in init_global () at i.cc:9
9 b[0] = 1;
(gdb) l 9
4 std::vector&
5
6 static void init_global() __attribute__ ((constructor));
7 void init_global()
8 {
9 b[0] = 1;
10 }
11
12 int main()
13 {
(gdb) b 9
Breakpoint 1 at 0x400a21: file i.cc, line 9.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) Starting program: /home/andy/a.out
Breakpoint 1, init_global () at i.cc:9 init_global() 先執行了,b 還是空的。
9 b[0] = 1;
(gdb) p b
$1 = std::vector of length 0, capacity 0
(gdb) p b[0]
$2 = (int ) @0x0: &
GCC 6.2.0 (mingw):
(gdb) r
Starting program: C:UsersAndyDesktopa.exe
[New Thread 6056.0x1400]
[New Thread 6056.0xeac]
[New Thread 6056.0xfbc]
1
[Thread 6056.0xfbc exited with code 0]
[Thread 6056.0xeac exited with code 0]
[Inferior 1 (process 6056) exited normally]
(gdb) b 9
Breakpoint 1 at 0x401636: file i.cc, line 9.
(gdb) r
Starting program: C:UsersAndyDesktopa.exe
[New Thread 5776.0x15f8]
[New Thread 5776.0x2618]
[New Thread 5776.0x4f0]
Breakpoint 1, init_global () at i.cc:9
9 b[0] = 1;
(gdb) p b
$1 = std::vector of length 3, capacity 3 = {0, 0, 0}
這裡變成先初始化 b 再調用 init_global() 了。
推薦閱讀:
※為什麼 C 語言的輸入輸出函數比 C++ 的輸入輸出流要快?
※有沒有比較好的自學IT的網站?適用於不管是初學者還是其他段位的程序猿的網站?
※如何評價2016年藍橋杯決賽?