让我们头文件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