2011-03-30 23 views
6

我現在有一個問題,讓我感到困惑: 我有一段以C++編寫的軟件,並且與C中的庫鏈接。通常的在運行時GCC優化結果爲「未定義符號」

extern "C" { 
    #include <libheader.h> 
} 

一切正常,只要我不使用gcc的優化。一旦我打開-O1(因此是第一個優化級別),在運行期間,我會從該庫中獲取符號的「未定義符號」錯誤。但是,這個名字已經通過名稱修改,應該被禁用,因爲extern "C"

調用符號的函數被內聯,以防萬一。使用的編譯器是gcc 4.4.3。

我真的不知道要搜索什麼,所以如果你們其中一個可以給我一些這種行爲的理由,我會非常感激。

感謝您的支持。

+0

你可以刪除內聯(即使功能不內聯),看看它是否開始工作? – sashoalm 2011-03-30 12:08:50

+1

作爲@ satuon的建議的替代方法,是否可以讓內聯函數調用一個包裝C函數的C++函數,並查看它是否能夠開始工作? – 2011-03-30 12:11:11

+0

感謝您的回覆!我嘗試了兩個建議,但是,該符號仍未找到。 – Thilo 2011-03-30 13:38:09

回答

1

是否有可能定義調用內聯函數頭包括庫的頭沒有extern "C"包裝,和其他地方使用的包裝線?

您是否試過其他等級-O2

您是否嘗試取消內定功能?

+0

感謝您的想法。是的,正確文件的頭文件肯定使用'extern「C」'wrapper。 -O2和-O3具有相同的效果。如上所述,刪除內聯也無濟於事。 – Thilo 2011-03-30 13:57:42

+0

@Thilo具體來說,你刪除了內聯,並將頭文件中的函數移動到源文件中,這樣編譯器就不能決定自動內聯它了嗎? – 2011-03-30 14:31:07

+0

呃...謝謝你澄清。忘記將先前內嵌的函數移至源文件。這解決了這個問題。但是,結果並不是很優雅,因爲內聯函數可能會更快。 – Thilo 2011-04-08 06:02:58

3

如果您有一個函數在未內聯時定義但在內聯時未定義,那麼該問題應該很容易定義。

你已經使用了某個地方的函數而不包含它的頭文件。

查看所有調用此函數的文件,並確保包含標題。

0

extern "C" {...}包裝C頭並不總是有效; 通常,標題需要被設計爲與兩種語言一起工作,以便 他們能夠使用這兩種語言。

在這種情況下,沒有更多的細節,這是很難說究竟是什麼 發生,inline關鍵字意味着C和在 C++不同的東西;我不希望帶有inline函數的標題以這種 方式工作。 (我不希望出現症狀,但他們 也不會讓我感到意外。)

處理此問題的正確方法是堅持要求 庫的供應商提供標題,旨在用這兩種語言工作。

如果不成功,處理這個問題的正確方法是編寫自己的 C代碼,它包含頭文件幷包裝所有需要的函數,併爲此C代碼編寫自己的頭文件至 包括在兩種語言中。我承認,這是很多工作; 得到供應商做他的工作,而不是他的一半爲 他。

4

你說你在extern "C"塊中包含libheader.h文件,但鏈接器正在尋找的符號已經被名字弄亂了。

就是這樣libheader.h也被包括在extern "C"塊外的指示(在包括內部的extern "C"塊可能是由於包括在libheader.h警衛一個NOP)。

尋找可能包含libheader.h的其他方法。海灣合作委員會的-E和/或各種-M選項可能有助於解決這個問題。或者(如果僅用於測試)移動內部libheader.hextern "C"塊:

// at start of libheader.h: 
#ifdef __cplusplus 
extern "C" { 
#endif 

/* existing contents of libheader.h */ 
// ... 

// at end of libheader.h: 
#ifdef __cplusplus 
} 
#endif 

需要注意的是聯動的規格可以嵌套,所以你不必在#include網站刪除現有extern "C"塊。

我不知道爲什麼這個問題只會發生在優化構建中,不同之處在於包含調用函數的非內聯版本的.c或.cpp文件可以正確獲取標題,並且只需要成爲一個翻譯單元,它會使標題錯誤,並調用調用函數來查看問題。

+0

謝謝!如果這就是原因,那麼如何找出問題可能是一個好主意。可悲的是,我只有在下週星期五纔有時間研究它,會在那時報告。 – Thilo 2011-03-31 07:09:05