2

我有一个服务器库,我的客户端可执行文件将其注入远程进程。服务器负责设置某种 IPC/RPC 实现以允许客户端与远程进程无缝通信。

更新

查看以下服务器端标头:

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
using namespace boost::interprocess;

typedef allocator<int, managed_shared_memory::segment_manager> ShmIntAllocator;
typedef vector<int, ShmIntAllocator> IntVector;

class A
{
public:
    A();
    A(string str, offset_ptr<IntVector> ints)
        : m_str(string(str)), m_ints(ints) {};
    ~A();

    string m_str;
    offset_ptr<IntVector> m_ints;
};

class B
{
public:
    B();
    B(offset_ptr<A> obj) : m_obj(obj);
    ~B();
    VOID DoSomethingUseful()
    {
        MessageBoxA(NULL, m_obj->m_str.c_str(), "SomethingUseful", MB_ICONINFORMATION);
    }

    offset_ptr<A> m_obj;
};

这是服务器端的实现:

managed_shared_memory g_shm;
offset_ptr<A> g_objA = nullptr;
PVOID g_hMem = nullptr;

BOOL StartServer()
    // Create a shared memory pool
    try {
        g_shm = managed_shared_memory(create_only, "MySharedMem", OVR_MAPSIZE);
    } catch(interprocess_exception& e) {
        std::string msg(e.what());
        MessageBoxA(NULL, msg.c_str(), "Error", MB_ICONERROR);
        return FALSE;
    }

    // Construct a local class instance
    const ShmIntAllocator alloc_intVector (g_shm.get_segment_manager());
    offset_ptr<IntVector> ints = g_shm.construct<IntVector>(unique_instance)(alloc_intVector);
    ints->push_back(10);
    ints->push_back(20);
    ints->push_back(30);
    g_objA = new A("Testing", ints);
    B objB(g_objA);

    // Copy data into shared memory
    size_t len = sizeof(objB); // <-- Doesn't seem to make a difference if I set this to be something higher
    g_hMem = g_shm.allocate(len);
    std::memcpy(g_hMem, &objB, len);
    return TRUE;
}

VOID StopServer()
{
    // Free used resources

    if(g_objA) {
        delete g_objA;
        g_objA = nullptr;
    }

    try{
        g_shm.destroy<B>(unique_instance);
        g_shm.deallocate(g_hMem);
        g_hMem = nullptr;
        shared_memory_object::remove("MySharedMem");
    } catch(interprocess_exception& e) {
        std::string msg(e.what());
        MessageBoxA(NULL, msg.c_str(), "Error", MB_ICONERROR);
    }
}

和客户端实现:

BOOL Connect()
{
    // Grab the shared memory pool and extract the class
    managed_shared_memory shm(open_only, "MySharedMem");
    std::pair<B*, std::size_t> ret = shm.find<B>(unique_instance); // <-- Always ends up being 0x00000000!
    B *objB = static_cast<B*>(ret.first);
    if(!objB) return FALSE;
    objB->DoSomethingUseful();
    return TRUE;
}


您会注意到managed_shared_memory::find()始终无法向客户端返回有效指针。但据我所知,代码是完全有效的。没有编译器警告或错误,到目前为止一切似乎都运行顺利。

那么为什么会失败呢?我怎样才能让它按预期工作?

4

2 回答 2

4

指针的不同地址空间

当你分享价值观时,一切都很清楚。例如,当把一个float值放在1234.5共享内存中时,在另一端你可以简单地读取它。

但是,当您共享复杂对象(包含指针)时,就会出现一个重要问题。两个进程的地址空间是完全不同且截然不同的。例如,您不能将std::vector对象放在共享内存中,因为它在 process1 中有一个指向其数据的指针,例如0x1ABF212,这个数字对 process2 没有意义。

所以,你必须将std::vector共享内存中的项目一一记下。阅读序列化技术以共享复杂数据。

此外,如果您坚持在进程之间共享复杂对象作为唯一对象,您可以使用特定的内存分配器来制作这些对象。

AFAIKBoost.Interprocess有那个分配器。它管理共享内存并在共享内存中创建对两个进程都有意义的指针。

抱歉含糊不清,我的英语不好

于 2013-05-13T04:35:37.123 回答
1

您试图找到应该由Unique 实例构造创建的 B 。Boost文档

find 函数获取指向唯一可以使用这种“唯一实例”机制创建的 T 类型对象的指针。

但是在您的代码中,您正在分配原始内存并仅复制您的 B 对象。所以你的 B 不是作为唯一实例创建的

所以我建议将您的代码更改如下:尝试使用

B &objB = *g_shm.construct<B>(unique_instance) (g_objA);

代替

B objB(g_objA);
于 2013-05-16T19:17:55.800 回答