=================================版权声明=================================
版权声明:原创文章 禁止转载
请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我
勿用于学术性引用。
勿用于商业出版、商业印刷、商业引用以及其他商业用途。
本文不定期修正完善。
本文链接:http://www.cnblogs.com/wlsandwho/p/6716215.html
耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html
=======================================================================
本文讲解了从一个DLL中导出的全局变量,在程序的多个不同DLL中使用时,该变量的行表现。
=======================================================================
Something、UserA、UserB是三个DLL,UserC是一个EXE。
Something在UserA、UserB中被调用,UserC调用了UserA和UserB。
=======================================================================
Something.h
1 #pragma once 2 3 #ifdef SOMETHING_EXPORTS 4 #define SOMETHING_API __declspec(dllexport) 5 #else 6 #define SOMETHING_API __declspec(dllimport) 7 #endif 8 9 10 extern SOMETHING_API int nGlobalVarInDLL;
Something.cpp
1 #include "stdafx.h" 2 #include "Something.h" 3 4 5 SOMETHING_API int nGlobalVarInDLL = 233;
=======================================================================
UserA.h
1 #pragma once 2 3 #ifdef USERA_EXPORTS 4 #define USERA_API __declspec(dllexport) 5 #else 6 #define USERA_API __declspec(dllimport) 7 #endif 8 9 10 class USERA_API CUserA 11 { 12 public: 13 void DoSet(); 14 void DoGet(); 15 };
UserA.cpp
1 #include "stdafx.h" 2 #include "UserA.h" 3 4 #include <iostream> 5 6 #include "Something.h" 7 #pragma comment(lib,"Something.lib") 8 9 10 void CUserA::DoSet() 11 { 12 std::cout <<"In UserA,nGlobalVarInDLL= "<< nGlobalVarInDLL <<" addr= 0x"<<(long)&nGlobalVarInDLL << std::endl; 13 nGlobalVarInDLL = 1; 14 std::cout << "In UserA,We set nGlobalVarInDLL= " << nGlobalVarInDLL <<std::endl; 15 } 16 17 void CUserA::DoGet() 18 { 19 std::cout << "In UserA,nGlobalVarInDLL= " << nGlobalVarInDLL << " addr= 0x" <<(long)&nGlobalVarInDLL << std::endl; 20 }
=======================================================================
UserB.h
1 #pragma once 2 3 #ifdef USERB_EXPORTS 4 #define USERB_API __declspec(dllexport) 5 #else 6 #define USERB_API __declspec(dllimport) 7 #endif 8 9 10 class USERB_API CUserB 11 { 12 public: 13 void DoSet(); 14 void DoGet(); 15 };
UserB.cpp
1 #include "stdafx.h" 2 #include "UserB.h" 3 4 #include <iostream> 5 6 7 #include "Something.h" 8 #pragma comment(lib,"Something.lib") 9 10 void CUserB::DoSet() 11 { 12 std::cout << "In UserB,nGlobalVarInDLL= " << nGlobalVarInDLL << " addr= 0x" << (long)&nGlobalVarInDLL << std::endl; 13 nGlobalVarInDLL = 2; 14 std::cout << "In UserB,We set nGlobalVarInDLL= " << nGlobalVarInDLL << std::endl; 15 } 16 17 void CUserB::DoGet() 18 { 19 std::cout << "In UserB,nGlobalVarInDLL= " << nGlobalVarInDLL << " addr= 0x" << (long)&nGlobalVarInDLL << std::endl; 20 }
=======================================================================
UserC.cpp
1 #include "stdafx.h" 2 3 #include "UserA.h" 4 #pragma comment(lib,"UserA.lib") 5 6 #include "UserB.h" 7 #pragma comment(lib,"UserB.lib") 8 9 10 int main() 11 { 12 CUserA oUserA; 13 CUserB oUserB; 14 15 oUserA.DoSet(); 16 oUserB.DoGet(); 17 18 oUserB.DoSet(); 19 oUserA.DoGet(); 20 21 return 0; 22 }
=======================================================================
调用结果
=======================================================================
结论就是:使用的是同一个地址空间,加载的是同一个变量。
(这篇就是给那些不想学操作系统知识的人看的。)
=======================================================================
20200826-01
这里再做个扩展。所以说看博客要看原文出处,不要看垃圾爬虫网站抓取的内容。
你看,时隔多年,我还更新了!
=======================================================================
UserD是一个EXE。
编写一个UserD.cpp
1 #include <iostream> 2 3 #include "Something.h" 4 #pragma comment(lib,"Something.lib") 5 6 int main() 7 { 8 std::cout << "In UserD,nGlobalVarInDLL= " << nGlobalVarInDLL << " addr= 0x" << (long)&nGlobalVarInDLL << std::endl; 9 10 getchar(); 11 12 return 0; 13 }
在Linker的Advanced里修改Base Address,这里我改了个0x20000000
运行UserC.exe和UserD.exe
发现地址不一样。
再运行一次。
发现地址又是一样的。
这里微软的意思是,不同进程加载同一个DLL,其载入的地址可能是一样的也可能是不一样的,但无论一样不一样,都是独立的互不影响的。