boost消息队列创建的共享内存太小?

Shared memory created by boost message queue is too small?

我正在创建一个应用程序,其中多个进程通过增强消息队列进行通信。队列是使用消息队列构造函数创建的 message_queue(open_or_create, name, max_num_msg, max_msg_size); 我对所有进程中的所有队列使用 open_or_create,因为没有指定创建队列的顺序。 max_num_msg = 200max_msg_size = 500000.

现在创建似乎一切正常,但是在通过队列发送消息一段时间后,由于读取访问冲突,我突然崩溃了。进行一些调试后,我找到了 message_queue.hppdo_send 的定义,其中获取了一个空消息头以写入消息

  //Insert the first free message in the priority queue
  ipcdetail::msg_hdr_t<VoidPointer> &free_msg_hdr = p_hdr->queue_free_msg(priority);

  //Sanity check, free msgs are always cleaned when received
  BOOST_ASSERT(free_msg_hdr.priority == 0);
  BOOST_ASSERT(free_msg_hdr.len == 0);

错误发生在free_msg_hdr.priority == 0,因为free_msg_hdr的地址没有指向可读的位置。

做更多的研究表明,在创建队列时,

template<class VoidPointer>
inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t,
    const char *name,
    size_type max_num_msg,
    size_type max_msg_size,
    const permissions &perm)
    //Create shared memory and execute functor atomically
    : m_shmem(open_or_create,
        name,
        get_mem_size(max_msg_size, max_num_msg),
        read_write,
        static_cast<void*>(0),
        //Prepare initialization functor
        ipcdetail::msg_queue_initialization_func_t<VoidPointer>(max_num_msg, max_msg_size),
        perm)
{}

创建的共享内存对象 m_shmem 的大小太小,无法容纳 200 条大小为 500000 的消息。这解释了为什么崩溃有点不可预测,因为仍然有一小部分内存可以访问,所以不小心进入人迹罕至的部分需要一些时间。但是,我仍然不知道为什么会这样。查看函数 get_mem_size(max_msg_size, max_num_msg) 它 returns 大小合适但创建后大小变小了。如果我然后重新创建相同的队列,它通常会得到正确的大小,而且我永远不会遇到任何异常。如果有人知道为什么会发生这种情况,或者对如何进一步调试此问题有任何建议,我们将不胜感激。

我应该提一下,该应用程序是在 32 位 Visual C++ 中编译的,并在 Windows 10 上运行。Windows 共享内存实现是否会导致这样的问题?

当 boost 库创建消息 queue 时,它会请求一块共享内存来保存 queue。我不知道它是如何工作的,也许它取决于 OS 实现,但是在 Windows 我可以在调试器中看到内存段的大小正在缓慢上升(调试器非常缓慢附加,这就是我注意到的原因),而获得的共享内存充满了零。在我们的例子中,其他进程在此期间附加到消息 queue ,显然获得了共享内存的当前大小。但是,内存开头的 queue header 告诉它应该更大,因此第二个进程最终将访问尚未映射到其地址的内存范围内的消息 space, 生成读取访问冲突。

在我们的例子中,确保其他进程只在我们确定 queue 创建后才打开它相对容易,因此我们的问题就解决了!