2011-09-21 51 views
0

我有一個c代碼,可以在Linux中使用gcc編譯。但是,當我嘗試編譯使用Microsoft Visual Studio C++ 2008 Express版本,使用IDE,它顯示了錯誤無法編譯c代碼使用微軟視覺工作室C++ 2008 express版

vec.obj : error LNK2005: _INIT_SETA already defined in a.obj 
fatal error LNK1169: one or more multiply defined symbols found 

我查了一下頭文件和所有的人都預處理器守衛,防止頭被多次包括,例如

#ifndef _vec_h_ 
#define _vec_h_ 

然後我試圖編譯它在Visual Studio命令提示符下,

cl main.c 

它可以編譯。問題是什麼?

+0

您是否嘗試過清潔解決方案/項目並重建它? Visual Studio可能會每次都以不同的順序編譯文件(或者您只需要更改一個需要重新編譯的文件),因此您可能會使用早期的obj文件,並且定義已經存在? –

+0

謝謝尼克!這真的有幫助!我排除了所有文件,只有main.c在項目中,現在它可以編譯。感謝Pratorian和Daniel,我想這確實是鏈接問題,但不知何故只有main.c解決了問題 – Michael

回答

0

I checked the header files, and all of them have the preprocessor guard to prevent the header to be included multiple times
這隻能防止預處理器在單個編譯單元(cpp文件)中多次包含單個頭文件。因此,您仍然擁有包含在兩個cpp文件中的頭文件,並且該頭文件定義了一個_INIT_SETA對象。如果標題僅包含聲明而不包含定義,則可避免該問題。 (沒有函數代碼,也沒有全局變量。)

HPP文件:

#ifndef _vec_h_ 
#define _vec_h_ 
class vector { 
    function(); //function prototype. No definition 
}; //class declaration. No instantiation 
extern vector myvector; //variable declaration. No instantiation 
#endif //_vec_h_ 

cpp文件:

#include "vec.h" 

vector::function() {} //function definition only in this cpp file 

vector myvector; //variable instantiation only in this cpp file 

唯一例外的是通常的模板,其中完全去在頭文件,並且所述接頭數字出來本身。

1

「找到一個或多個乘法定義的符號」是鏈接器錯誤而不是編譯器錯誤。它發生在兩個或多個目標文件包含相同符號的定義時。在這種情況下,vec.obja.obj在某種程度上都包含_INIT_SETA符號的條目,因此您需要弄清楚vec.obja.obj的源各自如何將_INIT_SETA符號引入其各自的翻譯單元(編譯)中。

請注意_INIT_SETA是C標識符INIT_SETA的編譯器生成的符號。可能通過宏擴展內聯了INIT_SETA的定義?在這種情況下,INIT_SETA的聲明可能需要聲明爲static

「多符號」問題的存在不會影響源文件的編譯;而鏈接步驟將失敗,因爲鏈接器不知道要鏈接哪個_INIT_SETA條目。

1

您發佈的錯誤表示存在vec.ca.c(假設您沒有嘗試鏈接預先存在的對象文件),它們都定義爲INIT_SETA。這是一個鏈接器錯誤,而不是編譯錯誤。

cl main.c只編譯文件,目標文件,沒有鏈接回事。如果您嘗試使用命令行中的(link.exe)將所有對象文件鏈接在一起,則仍然會出現相同的錯誤。在錯誤中列出的兩個文件中搜索INIT_SETA符號的多個定義。

一個可能的解決辦法是用它來聲明它在這兩個文件中的一個extern,那麼這兩個文件將共享相同的實例。

如果兩個文件都需要私人副本,則應該取出任何出現在頭文件中的extern INIT_SETA聲明(並將static添加到每個源文件中的定義)。