2014-12-05 89 views
0

我有一些代碼似乎並不工作。C++ deque throw Segfaults

我想使一個deque(的結構),它是一個類的靜態成員。 骨架/基本代碼如下(I都保留所有數據類型 - my_typedef_fn是由typedef的-ING函數指針有一個數據類型):

1.H文件:

class A { 
    struct Bstruct { 
     char * b_name; 
     my_typedef_fn b_func; 
    } 
    static std::deque<Bstruct> a_deque; 
    static void func(); 
} 

1.cpp文件:

std::deque<A::Bstruct> A::a_deque; 
void A::func(char * name, my_typedef_fn fn) { 
    a_deque.push_front((Bstruct) {name, fn}); // <<<< segfault ! 
} 

從我的理解 - .h文件只是聲明瞭的東西(像往常一樣) - 中的.cpp第一行初始化a_deque 靜態成員 - 功能func使用push_back添加東西到德克

但我得到一個分割錯誤在push_front被調用的線(使用gdb找到這個)。

而且,當我打印a_deque.size()之前push_front我的段錯誤 之前獲得4294967264當我使用計數雙端隊列的元素個數for循環:

int counter = 0 
for(std::deque<Bstruct> it = a_deque.begin(); it != a_deque.end(); it++, counter++); 

我的計數器顯示0元要在

所以,我不明白爲什麼我得到一個段錯誤,也不爲什麼.size()是一個大型垃圾數量

- 編輯1 - 添加函數的調用方式:

2.cpp

#include "1.h" 
void fn1() { 
    // some code 
} 
A::func("abc", fn1); 

它遵守了命令:

g++ -c -w -fpermissive -o 1.o 1.cpp 
g++ -c -w -fpermissive -o 2.o 2.cpp 
g++ -o final 1.o 2.o 
+0

爲什麼不使用'std :: string'而不是'char *'?鑑於此,「名稱」是什麼,它是如何得到其價值的?使用char *作爲字符串數據並不像看起來那麼無害。 – PaulMcKenzie 2014-12-05 19:54:58

+1

構建元素的語法很奇怪。你的意思是'Bstruct {name,fn}'?我其實並不知道你的代碼是做什麼的,或者它爲什麼編譯,但它可能不是你想要的。 – 2014-12-05 19:55:06

+0

你是否正在調用來自全局構造函數的代碼,這可能導致'a_deque'在它有機會初始化之前被訪問?請修正像A:BStruct這樣的句法問題。 – Angew 2014-12-05 19:58:48

回答

2

這通常是不可能簡單地調用在全球範圍內的功能,就像你在2.cpp顯示。但是你提到的代碼是舊的,所以也許這是一個標準之前的事情,或者是一個擴展。

無論如何,您已經在2.cpp中顯示函數被調用,而靜態數據成員a_deque1.cpp中定義。這意味着你可能會陷入靜態初始化命令失敗。初始化/執行全局變量(例如靜態數據成員,顯然也是這種奇怪的獨立函數調用),以便它們出現在一個翻譯單元(= .cpp文件)中,但它們在翻譯單元中的順序未指定。

這意味着它是完全有可能A::func()a_deque構造已經用完,這可能很可能導致段錯誤(如雙端隊列的內部數據成員具有零或甚至可能隨機值)之前訪問a_deque

要解決這個問題,你必須以某種方式擺脫這種情況。一種選擇是將所有可訪問a_deque的全局代碼移動到1.cpp,並將其放在a_deque的定義之後。

另一種方法是與函數作用域的靜態變量,這是保證第一次使用之前被初始化爲取代a_deque

1.H

class A { 
    struct Bstruct { 
     char * b_name; 
     my_typedef_fn b_func; 
    } 
    static std::deque<BStruct>& a_deque(); 
    static void func(); 
} 

1.cpp

#include "1.h" 

std::deque<A::BStruct>& A::a_deque() 
{ 
    static std::deque<BStruct> d; 
    return d; 
} 

void A::func(char * name, my_typedef_fn fn) { 
    a_deque().push_front((Bstruct) {name, fn}); // <<<< hopefully no more segfault 
} 
+0

這很有道理!這段代碼基本上用於將一些函數與一些名稱關聯起來 - 因此當用戶給出特定名稱時可以調用特定的函數。還有幾十個這樣的功能 - 它們本身非常龐大和模塊化(跨越7-8個文件)......你能以其他方式提出建議嗎?你認爲gcc中可能存在一個標誌來解決這個問題嗎?或者,在編譯事物的最後一步中,我使用1.o還是2.o的順序?我知道它在2002年工作:P我寧可不返工整個結構 – AbdealiJK 2014-12-05 20:40:08

+0

@AJK我已經添加了一個替代解決方案,應該工作,無論全局初始化順序。 – Angew 2014-12-05 20:53:51

+0

WOAH - EPIC回答! – AbdealiJK 2014-12-05 21:04:12