C++ 32位和64位进程之间的进程间共享内存

C++ 32位和64位进程之间的进程间共享内存,c++,windows,boost-interprocess,C++,Windows,Boost Interprocess,我试图让boost::interprocess在32位和64位进程之间共享内存。这表明在我使用的Boost 1.49中可能会出现这种情况 作为一个测试,我尝试共享一个无符号int。这是一个带有两个按钮的简单Qt应用程序 #define SHARED_MEMORY_NAME "My shared memory" #define SHARED_VAR_NAME "testVar" namespace bip = boost::interprocess; void on_createMemButto

我试图让boost::interprocess在32位和64位进程之间共享内存。这表明在我使用的Boost 1.49中可能会出现这种情况

作为一个测试,我尝试共享一个无符号int。这是一个带有两个按钮的简单Qt应用程序

#define SHARED_MEMORY_NAME "My shared memory"
#define SHARED_VAR_NAME "testVar"
namespace bip = boost::interprocess;

void on_createMemButton_clicked()
{
  std::cout << "sizeof(unsigned int): " << sizeof(unsigned int) << std::endl;
  bip::shared_memory_object::remove(SHARED_MEMORY_NAME);
  bip::managed_shared_memory mem(bip::create_only, SHARED_MEMORY_NAME, 12345);
  mem.construct<unsigned int>(SHARED_VAR_NAME)(42);
  std::cout << "Created shared memory " << SHARED_MEMORY_NAME << std::endl;
}

void on_accessMemButton_clicked()
{
  try
  {
    std::cout << "sizeof(unsigned int): " << sizeof(unsigned int) << std::endl;
    bip::managed_shared_memory mem(bip::open_only, SHARED_MEMORY_NAME);
    std::pair<unsigned int*, size_t> p = mem.find<unsigned int>(SHARED_VAR_NAME);
    std::cout<< "got " << p.second << " numbers " << std::endl;
    if (p.second > 0)
      std::cout << "first number is: " << *p.first << std::endl;

    bip::shared_memory_object::remove(SHARED_MEMORY_NAME);
  }
  catch (bip::interprocess_exception e)
  {
    std::cout << "Shared mem " << SHARED_MEMORY_NAME << " not found" << std::endl;
  }
}
#定义共享内存名“我的共享内存”
#定义共享变量名称“testVar”
名称空间bip=boost::进程间;
在\u createMemButton\u单击()时无效
{

std::cout我也遇到了同样的问题。我在另一个进程中运行了一个DLL,并单独编译了一个控制器应用程序。我的find()和find_或_construct()将挂起,使它看起来像一个死锁。更改为null_mutex_族没有任何作用

问题是用于编译DLL的字符类型与控制器应用程序的字符类型不同。将两者都设置为使用多字节字符为我解决了这个问题(使用MSVC)

我将这一行添加到我的代码中,这样它就再也不会像那样咬我了,就在访问我的托管共享内存实例之前

if (sizeof(char) != 2) throw std::exception("Set your chars right");

如果您尝试从使用另一种类型的应用程序中查找并使用一种类型的字符构造对象,boost将挂起一个无休止的循环(我没有耐心尝试查找).

在VS2019中,我在Windows上遇到了同样的问题,使用vc142工具集进行编译。我使用了boost 1.73,但我认为boost 1.60+也可以工作。此外,我使用的是Windows托管内存,而不是原始提问者使用的常规托管内存。但我认为我的解决方案仍然适用

在我注意到这一点后,我在编译时解决了这个问题

    using ManagedShMem = bip::managed_windows_shared_memory;
    ManagedShMem segment(bip::open_or_create, pcShMemName, uiMemSize, 0, perms); // will have issues, if used for crossplatform interaction.
在我的32位平台上,它实际上调用了这个构造函数:

    boost::interprocess::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,boost::interprocess::iset_index>(boost::interprocess::open_or_create_t __formal, const char * name, unsigned int size, const void * addr, const boost::interprocess::permissions & perm);
boost::进程间::基本的\u托管的\u窗口\u共享的\u内存::基本的\u托管的\u窗口\u共享的\u内存(boost::进程间::打开的\u或\u创建的\u t\u形式化,常量字符*名称,未签名的整数大小,常量无效*地址,常量boost::进程间::权限和perm);
而在64位平台上:

    boost::interprocess::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>(boost::interprocess::open_or_create_t __formal, const char * name, unsigned __int64 size, const void * addr, const boost::interprocess::permissions & perm);
    using ManagedShMem = bip::basic_managed_windows_shared_memory
    <char,
    boost::interprocess::rbtree_best_fit<
        boost::interprocess::mutex_family,
        boost::interprocess::offset_ptr<
            void,
            __int64,
            unsigned __int64,
            0>,
        0>,
    boost::interprocess::iset_index>;
    ManagedShMem segment(bip::open_or_create, pcShMemName, uiMemSize, 0, perms); // now works well on both platforms!
boost::进程间::基本的\u管理的\u窗口\u共享的\u内存::基本的\u管理的\u窗口\u共享的\u内存(boost::进程间::打开的\u或\u创建的\u t\u正式的,常量字符*名称,未签名的\u int64大小,常量无效*地址,常量boost::进程间::权限和perm);
正如您所看到的,偏移量ptr的模板参数在两者之间是不同的。这导致32位和64位进程之间的二进制布局假设有所不同,这进一步导致使用共享内存的问题

您需要做的就是使托管段类型在所有平台上完全相同。因此,我的解决方案很简单——只需显式列出模板参数,并与64位平台兼容即可:

    boost::interprocess::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>::basic_managed_windows_shared_memory<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,__int64,unsigned __int64,0>,0>,boost::interprocess::iset_index>(boost::interprocess::open_or_create_t __formal, const char * name, unsigned __int64 size, const void * addr, const boost::interprocess::permissions & perm);
    using ManagedShMem = bip::basic_managed_windows_shared_memory
    <char,
    boost::interprocess::rbtree_best_fit<
        boost::interprocess::mutex_family,
        boost::interprocess::offset_ptr<
            void,
            __int64,
            unsigned __int64,
            0>,
        0>,
    boost::interprocess::iset_index>;
    ManagedShMem segment(bip::open_or_create, pcShMemName, uiMemSize, 0, perms); // now works well on both platforms!
使用ManagedShMem=bip::基本\u管理的\u窗口\u共享的\u内存
,
0>,
boost::进程间::iset_索引>;
ManagedShMem段(bip::open_或_create,pcShMemName,uiMemSize,0,perms);//现在在两种平台上都能正常工作!
在此之后,我可以通过共享mem段让32位进程与64位进程对话(反之亦然)


另外,请记住,32位平台限制了您可以访问的内存量。根据经验,您不能获得超过2GB的内存(尽管我对1.5GB没有问题,但这取决于许多其他因素)这意味着,如果您决定在64位进程上分配2 GB或更多(这很容易实现),32位进程上的段构造函数将出现异常,因为boost(通过Win32 API)将拒绝映射这么大的内存块。

真奇怪……在Unix风格的操作系统上,我肯定会这样做,但我不知道它在Windows下是如何工作的。在跨体系结构代码的情况下,你应该使用类似于
uint32\u t
的东西,而不是
unsigned int
,这可能是一个问题,具体取决于你的编译器。我是使用Visual C++ 10编译器,使用Boost 1.50,在Windows上使用Sox-IPC进行通信,它的效果很好。我得到了同样的问题。结果:@ ViAtReUs我们直接使用Windows API(<代码> CreateFileMapping <代码>,<代码> CurATEMUTEX(NULL,FALSE,…)< /C>)。<代码> sieZOF(Car)
始终是
1
,因为
sizeof
是以
char
s来度量的。您的意思是
sizeof(TCHAR)
?还可以查看
static\u assert
以获得编译时而不是运行时验证。