
在实际项目中,有一个工程的类依赖比较奇怪,这边简单抽象一下:
一共有三个工程:
静态库MyLib.lib:里面定义了一个AA类;
动态库MyDll.dll:里面导出了一个BB类;
可执行程序main.exe:windows控制台可执行程序,直接使用了AA类和BB类。
问题分析
那么问题来了,p1和p2是一个值吗?
由于当时实际项目中使用时,当时的AA类并未在内存中保存状态,再加上自己也比较菜,所以半知半解地就没当回事。
但是最近刷到其他人也遇到这个问题,所以直接将当时的猜想验证一下。
基础知识:
1 动态库依赖静态库时,会静态库的代码复制进来;其导出信息为外部接口,动态库内部是一个完整的整体。
2 可执行程序依赖静态库时,也会将代码复制进来。
3 可执行程序依赖动态库时,只会记录相应的导入符号,运行时再去递归加载动态库及动态库所依赖的动态库。
从基础知识可以推断出,以上的例子,程序运行时在内存中的布局是这样的:
即MyDll.dll与main.exe中各包涵一份完整的MyLib.lib代码。
所以AA::global与AA::getGlobal存在了两份。
所以,在main.exe运行时,相当于在C++概念上存在了功能完全相同的两个类:AA与AA’。
其静态变量与成员函数指针应该都在不同的内存中。
使用静态变量的值、地址,成员函数指针等都可以进行验证。
静态库工程代码:
// .h
#pragma once
class AA
{
public:
AA();
~AA();
static int global;
static int* getGlobal();
};
// .cpp
#include "AA.h"
#include
AA::AA()
{
}
AA::~AA()
{
}
int * AA::getGlobal()
{
++global;
std::cout << "AA::getGlobal global: " << global << std::endl;
std::cout << "AA::getGlobal &global: " << &global << std::endl;
return &global;
}
int AA::global = 0;
动态库工程代码:
// .h
#pragma once
class _declspec(dllexport) BB
{
public:
BB();
~BB();
int* my_global;
};
// .cpp
#include "BB.h"
#include "../MyLib/AA.h"
#include
BB::BB()
{
std::cout << "BB::BB()" << std::endl;
my_global = AA::getGlobal();
std::cout << "BB::BB() my_global: " << my_global << std::endl;
}
BB::~BB()
{
}
可执行程序工程:
// .h
// #pragma once
class _declspec(dllimport) BB
{
public:
BB();
~BB();
int* my_global;
};
// .cpp
#include "../MyLib/AA.h"
#include "BB-import.h"
#include
int main()
{
int* p1 = AA::getGlobal();
std::cout << "main my_global: " << *p1 << std::endl;
std::cout << "main &my_global: " << p1 << std::endl;
BB bb;
int *p2 = bb.my_global;
std::cout << "main my_global: " << *p2 << std::endl;
std::cout << "main &my_global: " << p2 << std::endl;
return 0;
}
输出结果:
AA::getGlobal global: 1
AA::getGlobal &global: 00007FF75362D160
main my_global: 1
main &my_global: 00007FF75362D160
BB::BB()
AA::getGlobal global: 1
AA::getGlobal &global: 00007FF9F4D9D160
BB::BB() my_global: 00007FF9F4D9D160
main my_global: 1
main &my_global: 00007FF9F4D9D160
即:
对global的自增运算分别作用于两个不同的变量;且两个变量的虚拟内存地址分别为
00007FF75362D160
00007FF9F4D9D160
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)