当调用的DLL中有全局变量时调用它的多个实例是否共享同一个全局变量

时间:2022-09-30 23:29:44

当调用的DLL中有全局变量时调用它的多个实例是否共享同一个全局变量????? 收藏
当调用的DLL中有全局变量时调用它的多个实例是否共享同一个全局变量????

问题的起因原于自己在工作中需要调用一个动态库,而其中要用到一个全局的变量才能把需要的句柄给传出来,于是就想,如果有多个进程要调用这个动态库时,后面的进程调用同一个动态库时,是否会把以前调用同一个动态库时的全局变量的值改变?????

我猜想应该是不会的吧,于是带着这个疑惑,我写了一个示例程序来验证自己的想法。示例代码如下:

Step1

首先创建一个动态库工程globalTest,这个动态库中要有一个全局变量,为了更加明显的证明,我在这个动态库中定义了两个函数来操纵这个全局变量:

(1).def文件的代码如下:

LIBRARY globalTest

EXPORTS

    testGlobal

    showGlobal

(2).h文件的代码如下:

int testGlobal(int *global);

int showGlobal(int *global);

(3).cpp文件的代码如下:

// globalTest.cpp : Defines the entry point for the DLL application.

//

 

#include "stdafx.h"

 

int dllGlobal = 0;

 

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                                    )

{

    return TRUE;

}

 

int testGlobal(int *global)

{

       dllGlobal += 5;

       *global = dllGlobal;

       return 0;

}

int showGlobal(int *global)

{

       *global = dllGlobal;

       return 0;

}

然后编译生成DLL和LIB文件,供以下调用程序调用。

Step2

创建一个控制台程序callglobalTest,来调用上述DLL

(1).h文件的代码如下:

int testGlobal(int *global);

int showGlobal(int *global);

(2).cpp文件的代码如下:

#include <windows.h>

#include <stdio.h>

#include "callglobalTest.h"

int main()

{

       int test = 1;

       for(int i = 0; i < 4; i++)

       {

              testGlobal(&test);

              printf("test = %d /n",test);

              Sleep(3000);

       }

       showGlobal(&test);

       printf("test = %d /n",test);

       Sleep(5000);

       printf("Sleep 5000 End!!!!!");

       Sleep(5000);

       return 0;

}

然后将上述DLL和LIB文件拷贝到本工程目录下边,在此工程中添加上LIB文件,然后编译运行。

Step3

为了验证自己的猜测,要同时运行上述调用程序callglobalTest,同时运行结果如下:

<!--[if !vml]--><!--[endif]-->

可以看到同时运行时,第二次调用DLL并没有改变全局变量的值!!!!!

附录说明:

上述所说的问题其实就是:DLL与进程的地址空间问题。

一旦D L L的文件映像被映射到调用进程的地址空间中, D L L的函数就可以供进程中运行的所有线程使用。实际上, D L L几乎将失去它作为D L L的全部特征。对于进程中的线程来说,D L L的代码和数据看上去就像恰巧是在进程的地址空间中的额外代码和数据一样。当一个线程调用D L L函数时,该D L L函数要查看线程的堆栈,以便检索它传递的参数,并将线程的堆栈用于它需要的任何局部变量。此外, D L L中函数的代码创建的任何对象均由调用线程所拥有,而D L L本身从来不拥有任何东西。

例如,如果Vi r t u a l A l l o c函数被D L L中的一个函数调用,那么将从调用线程的进程地址空间中保留一个地址空间的区域,该地址空间区域将始终处于保留状态,因为系统并不跟踪D L L中的函数保留该区域的情况。保留区域由进程所拥有,只有在线程调用Vi r t u a l F r e e函数或者进程终止运行时才被释放。

如你所知,可执行文件的全局变量和静态变量不能被同一个可执行文件的多个运行实例共享。Windows 98能够确保这一点,方法是在可执行文件被映射到进程的地址空间时为可执行文件的全局变量和静态变量分配相应的存储器。Windows 2000确保这一点的方法是使用第1 3章介绍的写入时拷贝(c o p y - o n - w r i t e)机制。D L L中的全局变量和静态变量的处理方法是完全相同的。当一个进程将D L L的映像文件映射到它的地址空间中去时,系统将同时创建全局数据变量和静态数据变量的实例。

^-^呵呵,写到这里吧,手都累了,希望对大家有所帮助。

 
发表于 @ 2007年04月05日 23:09:00 | 评论( 2 ) | 编辑| 举报| 收藏


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhangyuanlovelife/archive/2007/04/05/1553530.aspx