我试图理解当具有全局变量和静态变量的模块动态链接到应用程序时会发生什么.通过模块,我的意思是解决方案中的每个项目(我使用visual studio工作很多!).这些模块内置于*.lib或*.dll或*.exe本身.
我知道应用程序的二进制文件包含数据段中所有单个转换单元(目标文件)的全局和静态数据(如果是const,则只读取数据段).
当此应用程序使用带有加载时动态链接的模块A时会发生什么?我假设DLL有一个全局和静态的部分.操作系统是否加载它们?如果是这样,他们在哪里被加载?
当应用程序使用带有运行时动态链接的模块B时会发生什么?
如果我的应用程序中有两个使用A和B的模块,则是如下所述创建的A和B的全局变量的副本(如果它们是不同的进程)?
DLL A和B是否可以访问应用程序全局变量?
(请说明你的理由)
引自MSDN:
在DLL源代码文件中声明为全局的变量被编译器和链接器视为全局变量,但加载给定DLL的每个进程都获得其自身的DLL全局变量副本.静态变量的范围仅限于声明静态变量的块.因此,默认情况下,每个进程都有自己的DLL全局变量和静态变量.
从这里:
当动态链接模块时,可能不清楚不同的库是否有自己的全局变量实例或者是否共享全局变量.
谢谢.
class Family {
static std::size_t identifier;
template<typename...>
static std::size_t family() {
static const std::size_t value = identifier++;
return value;
}
public:
template<typename... Type>
inline static std::size_t type() {
return family<std::decay_t<Type>...>();
}
};
std::size_t Family::identifier{};
Run Code Online (Sandbox Code Playgroud)
用法:
const auto id = Family::type<FooBar>();
Run Code Online (Sandbox Code Playgroud)
它适用于我的目的,但它有一些局限性.最令人讨厌的问题(问题的目的)是,当链接到共享库的可执行文件使用它时,它会失败,如果它们都尝试创建标识符的话.结果通常是第n个标识符跨越边界分配给不同类型,因为每个共享库都保持它们自己的独立Family::identifier.
一些共享库的人指出,一个更可靠的解决方案将被赞赏,但没有提出一个没有破坏性能(几乎所有这些都引入容器,找到功能和内存分配).
是否有任何替代方法可以解决上述限制而不会失去当前设计的性能?
我搜索了SO并找到了一些有趣的答案.其中很多都是几年了.我想探索最新版标准的解决方案,只要现有类的接口保持不变.
这是最有趣的一个.它使用静态成员的地址来实现相同的目的,但它不符合顺序生成的标识符的想法
注意:不幸的是,使用RTTI不是一个选项.
注意:必须按顺序生成ID,并从0开始,如上面的解决方案所示.
可能重复:
C++中的内联函数
如果我在其头文件中完全实现一个类,编译器会做什么?一个典型的例子如下:
class MyException
{
public:
explicit MyException(const char* file, int line) file(file), line(line) {};
const char* getFile() const { return file };
int getLine() const { return line };
private:
const char* const file;
const int line;
};
Run Code Online (Sandbox Code Playgroud)
我的目的是使用这样的类:throw MyException(__FILE__, __LINE__).
我将此头文件包含在每个.cpp文件中.我想编译器将按照定义的次数编译该类,并将(相同的)机器代码包含在它生成的每个目标文件中.现在,链接器会做什么?我尝试了一个更简单的例子(没有所有那些讨厌const的东西)并且编译得很好.
会发生什么,如果不是简单的类,我在头文件中实现了一个三屏长的C函数?最后一个问题,我应该将我的例子分成.h和.cpp文件吗?