=================================版权声明=================================

版权声明:原创文章 禁止转载 

请通过右侧公告中的“联系邮箱(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,其载入的地址可能是一样的也可能是不一样的,但无论一样不一样,都是独立的互不影响的。