1. 程式人生 > >multiple definition of(變數或者函式)

multiple definition of(變數或者函式)

今天在公司寫專案的時候,遇到如下錯誤,半個小時了,沒看出來問題出在哪裡~


我看了好幾遍程式碼,確認沒有重定義,後來問旁邊的大牛,才發現自己手誤,錯吧#include “area.h”寫成#include"area.c",千萬得小心啊·有時候心裡想的跟手上寫的會不一樣哈。


於是寫這篇部落格以示警戒,並將這類錯誤的避免方法做以總結。

1,條件編譯是個好習慣

#ifndef TEST_H

 ...
#define TEST_H 

...
#endif 
條件編譯會獨立的解釋,然後生成每個檔案生成獨立的標示符,避免多次解釋。在編譯器連線時,就會將工程中所有的符號整合在一起,由於,檔案中有重名變數,於是就出現了重複定義的錯誤。


2,變數的唯一

 一般在.h檔案中定義一個變數宣告時,在其他檔案中只要包含了這個.h檔案,編譯的時候就會獨立被編譯器解釋,然後每個.C檔案會生成獨立的識別符號和符號表,所以上述程式碼在單獨編譯的時候並不會報錯,語法是合法的。但是,最後在編譯器連結的時候,就會將工程中所有的符號整合在一起,由於檔案中有重複的變數,於是就會出現重複定義的錯誤,系統就是提示你“multiple definition of `xxx`”。  進一步解釋,我們可以這樣想象編譯每一個C原始檔時,相當於一條有管道包圍的縱向水流,二者互不干擾。當連結時兩條原本相互獨立的水管橫向流了,所有就出現了重複的元素。所以當進行連結時就會出現重複定義的標示符。重複定義的標示符在這裡只是變數,函式不會。因為函式確實只在.c中定義了一次,多次宣告是沒有問題的,而變數確實出現了兩次定義。兩次重複的變數定義連結器就不知道該已那個地址作為變數的記憶體,所以報錯。
  其實只需要將全域性變數定義從.h檔案中挪到.c檔案裡,然後在.h檔案中用extern做外部宣告即可。即在.c檔案中宣告變數,然後在標頭檔案.h所有的變數宣告前加上extern,注意在.h檔案中就不要對變數進行初始化賦值了。然後其他需要使用全域性變數的.c檔案中包含.h檔案即可。編譯器會為.c生成目標檔案,然後連結時,如果該.c檔案使用了全域性變數,連結器就會連結到此.c檔案。其他檔案需要使用此全域性變數也是同樣的方式,目的其實只有一個,就是使變數在記憶體中唯一化。3函式的重定義很容易發現一般函式重定義,編譯伺服器會報錯,很容易解決,如下:
錯誤提示,row_trp_spc_init函式redefinition。

4,細心檢查很重要

專案比較大,檔案比較多的時候,會出現迴圈引用,你包含我 我又包含你的情況,所以得找到最根源的檔案,將兩者耦合的引用關係分離,在最外層的檔案中包含標頭檔案,避免重複引用。