2013-10-04 382 views
0

我有一個std::map,我保存一個指向類的指針。在類的構造函數中傳遞了幾個值,以便類中的變量具有實際值。我的問題在於,當我調用一個使用先前定義的變量之一的類的函數時,關鍵字this會產生分段錯誤。這看起來像這樣詳細(短版):「this」關鍵字導致分段錯誤

Command::Command(const char *name, commandHandler h) // commandHandler is a function pointer 
{ 
    this->name = name; 
    this->handler = h; 
} 

Command::execute(int cn, std::vector<char *> args) 
{ 
    if (this->handler != NULL) // "this" is according to gdb a pointer to a class Command at 0x0 
     (handler)(cn, args); 
} 

地圖是在一個靜態類,地圖元件插入在一個靜態函數。

編輯:由於意見和答案(謝謝你們): 我的指針添加到類的功能registerCommands()基本上創建使用Command *command_xxx = new Command("xxx", &(handler_func));指針並提出在地圖中的一個靜態類。該調用來自與map和registerCommands()函數在同一類中的另一個方法。類指針是使用commands.find("xxx")->second;獲得的,它返回null - >空指針。

+0

顯示調用代碼 – Kal

+0

根據上下文,確切的問題無法確定。根據描述,要調用該函數的對象將丟失,或者在調用成員函數時提供一個有趣的指針(例如空指針)。 –

回答

2

該類指針是使用commands.find("xxx")->second獲得的;它返回null - >空指針。

然後當你做commands.find("xxx")->second->execute(...)你會得到一個段錯誤。這裏至少有兩件事是錯誤的。

一個是->execute(...)而不檢查找到的項目是否非空。如果找到的項目爲空,則調用未定義的行爲。大多數系統會發生什麼情況取決於​​是否是虛擬功能。如果它是虛擬的,你會在通話之前得到段錯誤或總線錯誤。如果它不是虛擬的,底層機器就知道要調用哪個函數。當您嘗試訪問數據成員時,段錯將發生在​​函數內部。您應該知道指針不爲空或檢查它是否在調度對象調用之前。一旦你做了->execute()它的遊戲結束了,無論如何。其他問題是->second。如果"xxx"不在地圖中怎麼辦?如果不是,commands.find("xxx")將返回commands.end(),並且對此操作是未定義的行爲。所有你應該做的結束迭代器測試,你沒有打它。

它有點冗長,但你應該測試那些角落案件。即使經過艱苦的分析,您也應該100%自信地知道,您的find將始終返回入界迭代器,並且每個入界迭代器都有非空映射值。你可以通過斷言來測試,你最終可以關閉它們,但是你應該總是測試。總是。

+0

好像它不會保存地圖中的類指針。謝謝。 – user2610529

2

這種情況主要發生在您設置爲NULL的指針調用方法時。由於this是傳遞給每個成員函數的隱藏參數,因此GDB將其顯示爲NULL。例如:

Command *command = NULL; 
command->execute(...); 
2

你有一個指向Command地方,但指針0。這個指針然後用於呼叫Command::execute,這意味着成員函數被調用this == 0

雖然不符合標準的,你可以最有可能嘗試添加代碼來捕獲這並打印一些信息可能有助於調試問題:

if(!this) print_backtrace(); 

或類似的東西。 (對於Linux上的回溯,請參閱我不久前給出的this answer