我正在创建一个应用程序,其中多个进程通过boost消息队列进行通信。使用消息队列构造函数创建队列,如下所示:
message_queue(open_or_create, name, max_num_msg, max_msg_size);
我对所有进程中的所有队列都使用open_or_create,因为没有指定必须创建队列的顺序。
max_num_msg = 200
和max_msg_size = 500000
。
现在创建似乎一切正常,但是在队列中发送消息一段时间后,由于读取访问冲突,我突然崩溃。经过一些调试,我进入了do_send
中message_queue.hpp
的定义,其中获得了一个空消息头来编写消息
//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)
会返回正确的大小,但是创建后大小会变小。如果我随后重新创建相同的队列,通常它会得到正确的大小,并且我永远都不会收到任何异常。如果有人知道为什么会发生这种情况,或者对如何进一步调试此问题有任何建议,将不胜感激。
我可能应该提到该应用程序是在Visual C ++中以32位编译的,并且可以在Windows 10上运行。Windows共享内存实现是否会引起这样的问题?
答案 0 :(得分:0)
boost库创建消息队列时,它请求一块共享内存来保存该队列。我不知道它是如何工作的,也许取决于操作系统的实现,但是在Windows上,我可以在调试器中看到内存段的大小正在缓慢增加(在连接调试器的情况下,速度非常缓慢,这就是我注意到的原因)而获得的共享内存将填充零。在我们的情况下,这段时间内附加到消息队列的其他进程显然获得了共享内存的当前大小。但是,内存开头的队列标头表明它应该更大,因此第二个进程最终将访问它尚未映射到其地址空间的内存范围内的消息,从而产生读取访问冲突。
在我们的情况下,确保其他进程仅在确定队列已创建并因此解决了问题之后才打开队列是相对容易的!