【问题标题】:Windows Shared memory and different Compilers weird behaviorWindows 共享内存和不同的编译器奇怪的行为
【发布时间】:2014-08-06 17:04:02
【问题描述】:

我让两个不同的进程使用共享内存相互交互,我观察到由于某种原因它不能按预期工作,问题是,当我放入数据时,缓冲区由于某种原因被额外的零填满进去。这是我的工作:

Process1 vc++(msvc2012主动解决平台Win32):

LPTSTR pBuf =(LPTSTR) MapViewOfFile(hMap,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,
                        0,
                        256);
if(!pBuf)
{
        //handle errors
}
WaitForSingleObject(hExchangeData,INFINITE); //here i'm waiting data from the second process it should be DWORD value

DWORD someValue=0;
CopyMemory((PVOID)&someValue,pMemBuf,sizeof(DWORD)); //i get it and everything is ok, then the second process waits for this process to put some data in
int pBufSize=sizeof(DWORD); //counter
CopyMemory((PVOID)(pBuf+pBufSize),&hHandle1,sizeof(HANDLE));
pBufSize+=sizeof(HANDLE);
CopyMemory((PVOID)(pBuf+pBufSize),&hHandle1,sizeof(HANDLE));
SetEvent(exDone);

这里是流程二,用MinGW写的:线程模型:win32,gcc version 4.8.1 (GCC)

 pBuf = (LPTSTR) MapViewOfFile(hMap,
               FILE_MAP_WRITE | FILE_MAP_READ,
               0,
               0,
               256);

   if (pBuf == NULL)
   {
       //handle errors
   }
   DWORD myVal = 228;
   memcpy(pBuf,&myVal,sizeof(DWORD)); //here i wrote some dword in there which first process is successfully receiving
   SetEvent(dwordWritten); 
   int mySize = sizeof(DWORD); // counter
   WaitForSingleObject(handlesWrittine,INFINITE); //waiting for some handles

   CopyMemory((PVOID)&myHandle1,(PVOID)(pBuf+mySize),sizeof(HANDLE));
   mySize += sizeof(HANDLE);
   CopyMemory((PVOID)&myHandle2,(PVOID)(pBuf+mySize),sizeof(HANDLE));

所以基本上在第一个进程(msvc)中,我写了两个长度为 4 字节的句柄,因为在两个版本上 sizeof(HANDLE) =4,我检查了 printf,并且我希望在第二个中也收到 4 个字节(mingw+gcc) 进程,但是发生的是第一个进程中的内存缓冲区结构看起来像这样

 1234 //dword
 0012  //handle1
 0013  //handle2

但在第二个过程中:

  1234 //dword
  0000  
  0012  //handle1
  0000  
  0013  //handle3

所以从第二个进程最后一个CopyMemory 指令我得到0012 句柄值。为什么会有这样的不同?为什么我在第二个过程中得到额外的零?我尝试将 msvc 平台用于两个进程,它工作正常,但使用 mingw,gcc 没有。

【问题讨论】:

  • 听起来像是成员变量的对齐和填充问题。
  • @CaptainObvlious 我需要将这三个变量对齐到零对齐?
  • pBuf 被声明为 LPTSTR 是问题所在。请参阅我的新答案。

标签: c++ c visual-c++ gcc shared-memory


【解决方案1】:

这次我看到了真正的问题。

pBuf 是 LPTSTR 类型。在 UNICODE 上构建的是一个短*指针。在 ANSI 构建中,这是一个 char* 指针。我怀疑您的 Visual Studio 项目在构建环境中定义了 UNICODE,而 MinGW 没有。因此,第一个代码示例中 CopyMemory 调用中的这个表达式:

(pBuf+mySize)

计算 pBuf 增加 mySize*2 个字节。

简单的解决方法是将 pBuf 声明为 LPSTR 类型或 char*。

char* pBuf = (char*) MapViewOfFile(hMap,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,
                        0,
                        256);

应该可以的。

【讨论】:

  • 谢谢,成功了!我对窗户类型的疏忽让我浪费了很多时间。
【解决方案2】:

几个问题。

首先,这条线看起来很离谱:

mySize += HANDLE;

这甚至可以编译吗?你不打算说mySize += sizeof(HANDLE)

无论如何,你确定 sizeof(HANDLE) 在 MinGW 中是 4 吗?我有疑问。

HANDLE 通常在<winnt.h>中定义如下

typedef void *HANDLE;

所以sizeof(HANDLE) 将是 4 或 8,具体取决于您是构建为 32 位还是 64 位版本。

我怀疑您的 Visual Studio 配置处于 32 位模式,因为这是通常的默认设置。你的 MinGW 版本是 64 位的。

如果您将 Visual Studio 项目配置为生成 64 位版本,您将看到相同的差异。

【讨论】:

  • 对不起,我正在编辑帖子并把代码弄乱了一点,是的,它是mySize += sizeof(HANDLE),我使用printf("sizeof(HANDLE)=%d\n",sizeof(HANDLE));检查了它等于4,另外我从控制台仔细检查了它带有print的gdb调试器。
  • 在任务管理器中我的进程也显示为process.exe*32
猜你喜欢
  • 2013-04-01
  • 2010-11-07
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多