gcc: multiple definition of [轉]


/home/tace/openav/source/SeamlessMessage/CPaoFlt.o: In function `CPaoFlt::get_m_strPrmair() const':
CPaoFlt.cpp:(.text+0x0): multiple definition of `CPaoFlt::get_m_strPrmair() const'
/home/tace/openav/source/SeamlessMessage/CPaoFlt.o:CPaoFlt.cpp:(.text+0x0): first defined here

 

gcc在編譯過程中報函數重復定義(multiple definition of)的錯誤,主要有以下幾點:

 

1. 在頭文件中定義了變量或者函數,而非聲明。譬如對於 foobar.h,

------------- foobar.h -----------
int foo = 10;
int bar()
{
 return 10;
}
------------- foobar.h -----------

當foobar.h 被同一 .c 文件多次引用時(可能是間接多次引用),編譯生成相應的 .o 文件,鏈接時候會報 foo bar 重復定義。
一個可能想到的方法是在頭文件中加入宏定義,防止頭文件被重復引用,如:

------------- foobar.h -----------
#ifndef FOOBAR_H__
#define FOOBAR_H__
int foo = 10;
int bar()
{
 return 10;
}
#endif /* FOOBAR_H__ */
------------- foobar.h -----------

如果你只有一個 .c 文件,你可能得到一個可以運行的程序。但如果你有兩個或以上的 .c 文件引用 foobar.h ,譬如 test1.c test2.c 引用了 foobar.h,則gcc -o a.out test1.c test2.c,鏈接時仍會報重復定義錯誤。

解決方法:在頭文件中只聲明函數、變量;對於 c++ 中的 inline 函數,在頭文件中定義(編譯的時候,inline 函數展開需要用到)。

對於 foobar.h 可以這樣修改,為 .h 文件建立相應的 .c 文件,.h 文件中聲明函數 .c 文件中定義函數,變量面前加修飾符 extern。

------------- foobar.h -----------
#ifndef FOOBAR_H__
#define FOOBAR_H__
extern int foo;
int bar();
#endif /* FOOBAR_H__ */
------------- foobar.h -----------

------------- foobar.c -----------
int foo = 10;
int bar()
{
 return 10;
}
------------- foobar.c -----------

另外 static 修飾符也可以限制變量、函數的作用域,不過和本文無關了。

 

2. 在鏈接時,使用命令 gcc -o foobar main.o foobar.o foobar.o,你可能會想,怎么可能寫出這樣愚蠢的命令,但如果工程很大,.o 文件很多的時候,foobar.o 在不經意的時候被重復引用。如在 makefile 中:

FOO_OBJ = foo1.o foo2.o foo3.o foobar.o
BAR_OBJ = bar1.o bar2.o bar3.o foobar.o

foobar : main.o $(FOO_OBJ) $(BAR_OBJ)
    gcc -o foobar main.o $(FOO_OBJ) $(BAR_OBJ)

錯誤出現了,而且很難查出來,特別是在維護別人程序的時候。本人不幸的花了兩天時間才找到原因,雖然很早的時候也懷疑過這個問題,結果因為大意忽略過去了。這樣修改就可以了:
foobar : main.o $(FOO_OBJ) $(BAR_OBJ)
    gcc -o $@ $^

啊哈,終於知道 makefile 為什么要設置 $^ 這個變量了:)  (注:$^ 所有不重復依賴文件,以空格分開)

 

3. 在 gcc 編譯的時候,加入 -Xlinker -zmuldefs 選項,但這只是強制編譯器做些手腳,程序的錯誤仍沒被改正。-Xlinker 告訴gcc將其后的選項-zmuldefs傳給鏈接器ld,也就是強制讓鏈接器忽略重復定義。

 

[轉] http://blog.csdn.net/ninthing/article/details/6014088

-------------------

 

 

我把所有的全局變量寫在一個global.h里,然后其他文件都include 了它 ,於是出現了 multiple   definition   of  .....

(編譯器 gcc )

后來在網上搜到了很多類似的錯誤,大家各有各的煩心事。

我的代碼結構

main.cpp
#include "global.h"

WinMain(....)
{
...
}

file_1.cpp
#include "global.h"
....

file_2.cpp
#include "global.h"

...

由於工程中的每個文件都是獨立的解釋的,
(即使頭文件有
#ifndef _x_h
....
#enfif   )

在其他文件中只要包含了global.h 就會獨立的解釋,然后生成每個文件生成獨立的標示符。在編譯器連接時,就會將工程中所有的符號整合在一起,由於,文件中有重名變量,於是就出現了重復定義的錯誤。


下面是解決方法:

在global.c(或.cpp)  中聲明變量,然后建一個頭文件global.h 在所有的變量聲明前加上extern ...
如 extern HANDLE ghEvent;
注意這兒不要有變量的初始化語句。

然后在其他需要使用全局變量的 cpp文件中包含.h 文件而不要包含 .cpp 文件。編譯器會為global.cpp 生成目標文件,然后連接時,在使用全局變量的文件中就會連接到此文件 。


--------------------------------------------------------------------------------------------------------------------------------------

今天Makefile的時候總是提示multiple definition of 的錯誤,也就是變量重復定義啦
可是我的程序里明明沒有多個定義,搞不清楚怎么回事,我把頭文件全部用頭文件保護符
給限定了,可是還是沒用,最后在網上搜了一下,解決方法其實很簡單,就是把編譯出錯
提示最先定義的地方使用static限定詞,限定為僅限在本文件中使用,就ok了

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

本人備注:在遇見這類問題時,要注意幾方面:1、不要重復包含頭文件,這會造成重復定義 2、當多個cc文件必須包含同一個頭文件時,對於static成員變量會出現重復定義。其中一種解決方法是在.h文件對該類變量只做聲明,如extern int a,而在另一個要使用該變量的.CC文件做定義初始化。但這種解決方法對於多個.c文件都需包含該頭文件的情況是不適用的,會出現錯誤,因為當無需該變量的.c文件編譯到extern int a鏈接不到相應的定義或者鏈接到了但會出現重復定義,因為是static變量。所以在這種情況下,最好在.h文件的類中,刪除該類成員變量,而只在需要該變量的.c文件做聲明定義,如在a.c文件定義 static int a = 0.或者不在頭文件刪除該成員變量,而將多個包含該頭文件的.cc文件合並成一個文件,不過這不是好的選擇,對於代碼的良好閱讀性而言

 

[轉] http://blog.sina.com.cn/s/blog_620882f40101199u.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM