讓我們頭文件var.h
爲什麼C++將在單獨模塊中定義的同名變量放入內存中的相同地址?
#include <iostream>
class var
{public:
var() {std::cout << "Creating var at " << this << std::endl; }
~var() {std::cout << "Deleting var at " << this << std::endl; }
};
和兩個源文件,第一lib.cpp
#include "var.h"
var A;
和第二app.cpp
#include "var.h"
var A;
int main()
{return 0;
}
然後,如果我嘗試編譯他們
g++ -c app.cpp
g++ -c lib.cpp
g++ -o app app.o lib.o
鏈接器返回乘法定義的變量錯誤。但是,如果我編譯到共享庫+主應用程序
g++ -fPIC -c lib.cpp
g++ --shared -o liblib.so lib.o
g++ -fPIC -c app.cpp
g++ -o app -llib -L . app.o
它鏈接沒有錯誤。然而,程序不能正常工作:
./app
Creating var at 0x6013c0
Creating var at 0x6013c0
Deleting var at 0x6013c0
Deleting var at 0x6013c0
所以不同的變量被創建在相同的內存地址!例如,當庫和應用程序期望它們具有不同的值(在這種情況下是對象字段的值)時,它可能會陷入嚴重的麻煩。
if class var
做內存分配/刪除valgrind警告訪問最近刪除的塊中的內存。
是的,我知道我可以把static var A;
而不是var A;
和兩種編譯方式將正常工作。我的問題是:爲什麼不能在不同的庫中使用同名變量(甚至函數?)?圖書館的創作者可能對彼此的名字一無所知,也不會被警告使用static
。爲什麼GNU鏈接不會警告這種衝突?
而且,順便說一句,dlload
可能會陷入同樣的麻煩?
UPD。謝謝大家解釋關於命名空間和外部,我明白了爲什麼相同的符號被放入同一個內存地址,但我仍然無法得到爲什麼沒有鏈接錯誤或甚至警告雙重定義的變量顯示,但在第二種情況下產生錯誤的代碼。
哦,我已經得到了有關的extern,它應該通過圖書館不應該工作?但我仍然困惑,爲什麼連接器提供無效的代碼沒有警告畢竟... – Nick 2012-01-01 16:04:43
我不知道。唉,我沒有足夠的共享庫和gcc知識來知道你是否應該以這種方式使用它們(因此,如果你發現奇怪的行爲,它就在你自己的頭上),或者如果這是真的GCC中的錯誤。 – Hurkyl 2012-01-02 06:08:16