gpt4 book ai didi

c++ - 为什么 C++ 将在不同模块中定义的同名变量放入内存中的相同地址?

转载 作者:太空狗 更新时间:2023-10-29 19:46:40 25 4
gpt4 key购买 nike

让我们使用头文件var.h

#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

所以在同一个内存地址创建了不同的变量!这可能会带来严重的麻烦,例如,在库和应用程序期望它们具有不同值(在这种情况下为对象字段的值)的情况下。

如果 class var 执行内存分配/删除 valgrind 警告访问最近删除的 block 中的内存。

是的,我知道我可以用 static var A; 代替 var A; 两种编译方式都可以正常工作。我的问题是:为什么不能在不同的库中使用同名变量(甚至函数?)?库创建者可能对彼此使用的名称一无所知,也不会被警告使用 static。为什么 GNU linked 不警告此冲突?

顺便说一句,dlload 会遇到同样的麻烦吗?

更新。谢谢大家对命名空间和外部的解释,我明白了为什么相同的符号被放置在相同的内存地址中,但我仍然不明白为什么没有链接错误甚至没有显示关于双重定义变量的警告,但在第二种情况下产生了错误的代码。

最佳答案

My question is: why one can't use same-named variables (or even functions?) in different libraries?

可以。你缺少的是声明

var A;

没有定义在库中使用的符号 A。他们正在定义要导出的符号,以便任何其他编译单元都可以引用它!

例如如果在 app.cpp 中,您声明了

extern var A;

这意味着声明“A 是一个 var 类型的变量,一些其他编译单元将定义和导出它”——通过对您的设置的这种修改,这将使 app.cpp 明确请求使用 lib.cpp 导出的名为 A 的对象。

您设置的问题是您有两个不同的编译单元都试图导出相同的符号 A,这会导致冲突。

Why GNU linked doesn't warn about this conflict?

因为 GNU 无法知道您希望 A 成为您的编译单元私有(private)的变量,除非您告诉 GNU 它应该对您的编译单元私有(private)。这就是 static 在此上下文中的含义。

关于c++ - 为什么 C++ 将在不同模块中定义的同名变量放入内存中的相同地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8693189/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com