* 有请微软专家: DLL的全局变量为什么不能拥有指针? 如何解决这个问题呢*

时间:2020-12-06 05:10:11
为什么不能这样呢? 是不是DLL new的空间地址属于分配时的那个进程空间, 然后别的进程肯定不能跨进程访问, 是这样吗?

如果是这样, 但是我又需要DLL中的全局变量能 拥有CList 结构体指针等等, 这些动态增长的数据怎么办呢?

谢谢!



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

#include "stdafx.h"
#include <string.h>
#include <stdio.h>


typedef struct tagMyData
{
tagMyData()
{
i=5;
strcpy(Path, "wo ai ni!");
}

int i;
char Path[MAX_PATH];

}MyData;

//定义全局变量数据
#pragma data_seg(".MySharedData")
int count=0;
MyData *g_Data= NULL;
#pragma data_seg()

#pragma comment (linker,"/SECTION:MySharedData,RWS");

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
if (count <=0 )
{
g_Data= new MyData;
}
count ++;

g_Data->i= count;

break;
}
case DLL_PROCESS_DETACH:
        count --;
        break;

default:
        break;
}
   return TRUE;
}

21 个解决方案

#1


不要告诉我用共享内存文件啊

还有COM技术, 因为COM初始化的时候太慢了, 不适合我的需要

#2


up

#3


全局共享段当然不能这么用了,你这么做的意思是:

1、g_Data是4个字节的全局共享段内存,类型为MyData*。
2、在进程A中,你给g_Data赋值,此时g_Data指向进程A的一块内存。
3、在进程B中,你要使用g_Data指向的内存,不过很不幸,这块内存是A的,不让你用。

#4


Dll拥有自己的空间,但一般是附在所属进程的内存空间上的。

#5


iamshuke() ( ):

难道只能通过共享内存文件来实现?

#6


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

#include "stdafx.h"
#include <string.h>
#include <stdio.h>


typedef struct tagMyData
{
tagMyData()
{
i=5;
strcpy(Path, "wo ai ni!");
}

int i;
char Path[MAX_PATH];

}MyData;

//定义全局变量数据
#pragma data_seg(".MySharedData")
int count=0;
#pragma data_seg()
MyData *g_Data= NULL;//此全局指针移到外面
#pragma comment (linker,"/SECTION:MySharedData,RWS");

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
if (count <=0 )
{
g_Data= new MyData;//分配内存
}
count ++;

g_Data->i= count;

break;
}
case DLL_PROCESS_DETACH:
            {
                  count --;
                  delete g_Data;//内存用完要释放
                  break;
            }

default:
        break;
}
   return TRUE;
}

其实你的意思,我还是不太明白,但你的程序有bug,做了一点小修改

如果你想多个进程共享一个MyData结构数据,你就应该在共享段中加入这个结构的变量,而不是指针,指针的在赋值时,是指向最后一次给他赋值的进程中的地址空间,由于指针处在共享内存段,所以当别的进程访问这个指针时,就肯定会发生异常

#7


if (count <=0 )
{
g_Data= new MyData;//分配内存
}
不好意思,没看到这句

#8


#pragma data_seg(".MySharedData")
int count=0;
MyDate stMyData={NULL}
MyData* g_Data=&stMyData;//以后就可以在所有进程中调用指针g_Data了
#pragma data_seg()

不知道改成这样,能不能符合你的要求

#9


可以看看剪贴板是怎么分配内存的。你了调用那几个分配内存的函数

#10


typedef struct tagMyData
{
tagMyData()
{
i=5;
strcpy(Path, "wo ai ni!");
}

int i;
char Path[MAX_PATH];

}MyData;

#pragma data_seg(".MySharedData")
int count=0;
char buffer[sizeof(MyData)] = { 0};
#pragma data_seg()

#pragma comment (linker,"/SECTION:MySharedData,RWS");

MyData * g_pData = (MyData *) buffer;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
count ++;

g_Data->i= count;

break;
}
case DLL_PROCESS_DETACH:
        count --;
        break;

default:
        break;
}
   return TRUE;
}

#11


如果是变长的,我都用内存文件实现,没试过其实方法.

#12



 herojx(酷酷):
FengYuanMSFT(袁峰 www.fengyuan.com) :

谢谢! 

但是你门误会我的想法了, 共享的数据的长度是可变的, 就像CList 变量那样

#13


iamshuke():
变长的,

那用在每个结构体中增加一个指针就可以了吗? 如果新分配的内存链接到共享内存中后, 其他进程能访问吗?

#14


up

#15


那用在每个结构体中增加一个指针就可以了吗? 如果新分配的内存链接到共享内存中后, 其他进程能访问吗?

------------------------------------
新分配的内存如果指向共享段,是可以用的,但共享内存段的大小是固定的,在程序编译时确定,所以如果在数据多少不确定的情况下(比如几K到几十M),都放这个段里不合适,总有一个上限吧,呵呵。

#16


ATL 速度 怎么样

#17



我决定采用 COM了, 唯一实例的那种模式

虽然COM初始化的时候其慢无比

#18


You can build a list with global memory handles, but it is slower than your current approach.

#19


typedef struct tagMyData
{
    int i;
    char Path[MAX_PATH];
}MyData;

#pragma data_seg(".MySharedData")
MyData g_Data= {0, 'w','o',' ','a','i',' ','n','i'};
#pragma data_seg()

#pragma comment (linker,"/SECTION:MySharedData,RWS");

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
)
{
     switch(ul_reason_for_call)
     {
       case DLL_PROCESS_ATTACH:
             ++g_Data.i;
             break;

       case DLL_PROCESS_DETACH:
            --g_Data.i;
            break;

       default:
            break;
    }
    return TRUE;
}

#20


变长共享数据 share节这种方式根本不可能

#21


不过假如估计数据不是很多,可以申请大一点的共享内存节,其实一个节至少4K,少申请也没有节约内存。

#1


不要告诉我用共享内存文件啊

还有COM技术, 因为COM初始化的时候太慢了, 不适合我的需要

#2


up

#3


全局共享段当然不能这么用了,你这么做的意思是:

1、g_Data是4个字节的全局共享段内存,类型为MyData*。
2、在进程A中,你给g_Data赋值,此时g_Data指向进程A的一块内存。
3、在进程B中,你要使用g_Data指向的内存,不过很不幸,这块内存是A的,不让你用。

#4


Dll拥有自己的空间,但一般是附在所属进程的内存空间上的。

#5


iamshuke() ( ):

难道只能通过共享内存文件来实现?

#6


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

#include "stdafx.h"
#include <string.h>
#include <stdio.h>


typedef struct tagMyData
{
tagMyData()
{
i=5;
strcpy(Path, "wo ai ni!");
}

int i;
char Path[MAX_PATH];

}MyData;

//定义全局变量数据
#pragma data_seg(".MySharedData")
int count=0;
#pragma data_seg()
MyData *g_Data= NULL;//此全局指针移到外面
#pragma comment (linker,"/SECTION:MySharedData,RWS");

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
if (count <=0 )
{
g_Data= new MyData;//分配内存
}
count ++;

g_Data->i= count;

break;
}
case DLL_PROCESS_DETACH:
            {
                  count --;
                  delete g_Data;//内存用完要释放
                  break;
            }

default:
        break;
}
   return TRUE;
}

其实你的意思,我还是不太明白,但你的程序有bug,做了一点小修改

如果你想多个进程共享一个MyData结构数据,你就应该在共享段中加入这个结构的变量,而不是指针,指针的在赋值时,是指向最后一次给他赋值的进程中的地址空间,由于指针处在共享内存段,所以当别的进程访问这个指针时,就肯定会发生异常

#7


if (count <=0 )
{
g_Data= new MyData;//分配内存
}
不好意思,没看到这句

#8


#pragma data_seg(".MySharedData")
int count=0;
MyDate stMyData={NULL}
MyData* g_Data=&stMyData;//以后就可以在所有进程中调用指针g_Data了
#pragma data_seg()

不知道改成这样,能不能符合你的要求

#9


可以看看剪贴板是怎么分配内存的。你了调用那几个分配内存的函数

#10


typedef struct tagMyData
{
tagMyData()
{
i=5;
strcpy(Path, "wo ai ni!");
}

int i;
char Path[MAX_PATH];

}MyData;

#pragma data_seg(".MySharedData")
int count=0;
char buffer[sizeof(MyData)] = { 0};
#pragma data_seg()

#pragma comment (linker,"/SECTION:MySharedData,RWS");

MyData * g_pData = (MyData *) buffer;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
count ++;

g_Data->i= count;

break;
}
case DLL_PROCESS_DETACH:
        count --;
        break;

default:
        break;
}
   return TRUE;
}

#11


如果是变长的,我都用内存文件实现,没试过其实方法.

#12



 herojx(酷酷):
FengYuanMSFT(袁峰 www.fengyuan.com) :

谢谢! 

但是你门误会我的想法了, 共享的数据的长度是可变的, 就像CList 变量那样

#13


iamshuke():
变长的,

那用在每个结构体中增加一个指针就可以了吗? 如果新分配的内存链接到共享内存中后, 其他进程能访问吗?

#14


up

#15


那用在每个结构体中增加一个指针就可以了吗? 如果新分配的内存链接到共享内存中后, 其他进程能访问吗?

------------------------------------
新分配的内存如果指向共享段,是可以用的,但共享内存段的大小是固定的,在程序编译时确定,所以如果在数据多少不确定的情况下(比如几K到几十M),都放这个段里不合适,总有一个上限吧,呵呵。

#16


ATL 速度 怎么样

#17



我决定采用 COM了, 唯一实例的那种模式

虽然COM初始化的时候其慢无比

#18


You can build a list with global memory handles, but it is slower than your current approach.

#19


typedef struct tagMyData
{
    int i;
    char Path[MAX_PATH];
}MyData;

#pragma data_seg(".MySharedData")
MyData g_Data= {0, 'w','o',' ','a','i',' ','n','i'};
#pragma data_seg()

#pragma comment (linker,"/SECTION:MySharedData,RWS");

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
)
{
     switch(ul_reason_for_call)
     {
       case DLL_PROCESS_ATTACH:
             ++g_Data.i;
             break;

       case DLL_PROCESS_DETACH:
            --g_Data.i;
            break;

       default:
            break;
    }
    return TRUE;
}

#20


变长共享数据 share节这种方式根本不可能

#21


不过假如估计数据不是很多,可以申请大一点的共享内存节,其实一个节至少4K,少申请也没有节约内存。