2013-06-03 109 views
0

我有一個接受函數指針作爲參數並調用函數指針的函數,如下所示。C++回調函數運行時錯誤

int foo (int a, int(*calc)(int)) 
{ 
    int y; 
    // .... 
    // calling calc function via callback 
    (*calc)(y); 
} 

Calc功能被稱爲背面看起來像

int calc(int x) 
{ 
    // .... 
    cout << x; 
    checkValue(x); 
} 

foo功能被放置在a.cpp和功能calc()checkValue()在文件b.cppc.cpp定義。我的問題是calc()執行正常,直到cout聲明並且未能調用checkValue()函數。我收到的崩潰報告是:

symbol lookup error:..... undefined symbol: _ZNSaIcEC1Ev, version GLIBCXX_3.4 

我該如何解決這個問題?

+0

用一個調試器運行它,並找出**正好**它崩潰的地方。它調用'checkValue()',但在其他地方崩潰。包含'foo'中的更多代碼,幷包含'checkValue()'的代碼,因爲它會在其中一個函數中崩潰。 –

+1

當您運行「ldd -r/path/to/your/programm」或「readelf -d/path/to/your/programm | grep PATH」時,它顯示的是什麼版本的libstdC++? –

+1

添加一個endl;在您的calc函數中使用cout語句之後。您可能沒有看到此輸出,因爲您沒有刷新流。或者使用調試器來驗證您沒有達到checkValue(x)行。 – ChrisCM

回答

0

符號_ZNSaIcEC1Ev對於std::allocator<char>::allocator()零參數的構造函數的重整名稱(我確定這使用c++filt(1)程序)。錯誤消息「symbol lookup error:..... undefined symbol」涉及動態鏈接,與通過函數指針調用函數無關。

你的錯誤幾乎肯定是在別的地方。由於stdout緩衝 - 字符串被打印到標準輸出,但您沒有看到它們出現,因爲它們被緩衝在內存中,然後該程序崩潰,您可能會對錯誤的位置感到困惑在他們被顯示之前。爲了避免這種情況,您需要確保在每次打印語句後刷新輸出(例如,插入std::cout << std::endlstd::cout << std::flush或明確調用std::cout.flush()),或者使用std::cerr而不是std::cout(默認情況下爲無緩衝)。

+0

我嘗試了你的建議。你的想法看起來合法。當我刷新每個cout語句時,程序崩潰而不執行回調中的任何語句。新錯誤是_ZNKSt9basic_iosIcSt11char_traitsIcEEcvPvEv,版本GLIBCXX_3.4。 我會盡力檢查出來。建議鼓勵:) – kona

+0

正如你所說,這是一個鏈接錯誤,但我花了相當一段時間來找出源。我的錯誤是試圖將一個空指針傳遞給回調函數。 – kona

0
#include <iostream> 
using namespace std; 

int calc(int x){ 
    cout<< "calc:" << x << endl; 
} 

int CALC(int x) { 
    cout << "CALC: " << x << endl; 
} 


int foo (int a, int(*callback)(int)){ 
    cout << "Calling calc on:" << a << endl; 
    (*callback)(a); 
} 

int main() { 
    cout << "START" << endl; 

    foo(5, calc); 
    foo(6, CALC); 
} 

這對我來說很好。

gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00) 

注:我刪除了你的「校驗值(X)」調用,問題可能出在那裏?