boost :: interprocess :: message_queue在第二个进程中没有收到消息 [英] boost::interprocess::message_queue no message received in second process
问题描述
我正在使用boost的消息队列编写仅包含两个char数组的基本类,但是即使 get_num_msg()
返回1之前,第二个进程中未接收到数据也是空的读取,读取后返回0.出于调试目的,我还尝试从相同的过程进行写入和读取,效果很好.我之所以使用共享指针,是因为之前只是读写整数,除非声明为共享ptr,否则它不会在接收方读取整数.
I am using boost's message queue to write a basic class with just two char arrays, but the data is not being received in the second process is empty, even though get_num_msg()
returns 1 before the read and returns 0 after reading. For debugging purposes I also tried writing and reading from the same process, and that worked fine. I am using the shared pointer because earlier while just reading and writing integers, it would not read the integer at the receiver unless it was declared as shared ptr.
class AccessQueue {
public:
char name[64];
char action[64];
AccessQueue(char name[64], char action[64]) {
strcpy(this->name, name);
strcpy(this->action, action);
}
AccessQueue() {}
};
发送功能
// std::shared_ptr<AccessQueue> p1;
this->p1.reset(new AccessQueue("asd", "vsq"));
try {
this->mq->send(&p1, sizeof(p1), 0);
} catch(boost::interprocess::interprocess_exception & ex) {
std::cout << ex.what() << std::endl;
}
接收功能
std::cout << this->mq->get_num_msg() << "\t" << this->mq->get_max_msg_size() << "\t" << this->mq->get_max_msg() << std::endl;
AccessQueue * a;
unsigned int priority;
boost::interprocess::message_queue::size_type recvd_size;
try {
this->mq->try_receive(&a, sizeof(AccessQueue), recvd_size, priority);
} catch(boost::interprocess::interprocess_exception & ex) {
std::cout << ex.what() << std::endl;
}
std::cout << this->mq->get_num_msg() << "\t" << this->mq->get_max_msg_size() << "\t" << this->mq->get_max_msg() << std::endl;
std::cout << "It clearly maybe works " << a->action << "\t" << a->name << std::endl;
在接收者端的输出:
1 128 20
0 128 20
推荐答案
看起来像p1(在发送函数中)是一个智能指针(例如 std :: unique_ptr
或 std :::shared_ptr
).在这种情况下
Looks like p1 (in the sending function) is a smart pointer (like std::unique_ptr
or std::shared_ptr
). In that case
this->mq->send(&p1, sizeof(p1), 0);
显然是错误的,因为它将指针对象放置在队列中,而不是数据结构中.使用
is obviously wrong, because it puts the pointer object on the queue, instead of the data structure. Use
this->mq->send(*p1, sizeof(*p1), 0);
或者,实际上,一开始就不要使用动态分配:
Or, indeed, don't use dynamic allocation in the first place:
AccessQueue packet("asd", "vsq");
mq.send(&packet, sizeof(packet), 0);
哦,还有更多
在接收方,有一个类似的问题:
Uhoh there's more
On the receiving side, there's a similar problem:
AccessQueue * a;
// ..
mq.try_receive(&a, sizeof(AccessQueue), ...);
那将接收INTO指针,而不是对象.您甚至没有对象,因为 a
(指针)从未初始化.这里的修复在语法上很简单:
That receives INTO the pointer, not the object. You don't even have an object, because a
(the pointer) is never initialized. Here the fix is syntactically simple:
AccessQueue a;
没有更多的指针.现在, a
是一个对象,而& a
是该对象的地址.
No more pointers. Now, a
is an object and &a
is the address of that object.
请注意原始格式是 UB ,因为您阅读了
sizeof(AccessQueue)
字节放入一个指针.但是,指针只有8个字节,而结构是128个字节.糟糕!
Note how the original was UB because you read
sizeof(AccessQueue)
bytes into a pointer. However the pointer is only 8 bytes and the struct is 128 bytes. Ooops!
简化的工作演示
这有效:
Live On Wandbox¹
#include <boost/interprocess/ipc/message_queue.hpp>
#include <iostream>
#include <iomanip>
namespace bip = boost::interprocess;
using MQ = bip::message_queue;
template<size_t N>
static inline void safe_copy(std::array<char, N>& dst, std::string_view src) {
std::copy_n(src.data(), std::min(src.size(), N), dst.data());
dst.back() = 0; // make sure of NUL termination
}
struct AccessQueue {
std::array<char, 64> name{0};
std::array<char, 64> action{0};
AccessQueue(std::string_view n = "", std::string_view a = "") {
safe_copy(name, n);
safe_copy(action, a);
}
};
static_assert(std::is_standard_layout_v<AccessQueue>);
struct X {
void send() {
AccessQueue packet("asd", "vsq");
try {
mq.send(&packet, sizeof(packet), 0);
} catch(std::exception const & ex) {
std::cout << ex.what() << std::endl;
}
}
AccessQueue receive() {
AccessQueue retval;
report();
try {
unsigned int priority;
MQ::size_type recvd_size;
mq.try_receive(&retval, sizeof(AccessQueue), recvd_size, priority);
} catch(std::exception const & ex) {
std::cout << ex.what() << std::endl;
}
report();
return retval;
}
void report() {
std::cout << mq.get_num_msg() << "\t" << mq.get_max_msg_size() << "\t" << mq.get_max_msg() << std::endl;
}
MQ mq { bip::open_or_create, "somequeue", 10, sizeof(AccessQueue) };
};
int main() {
X tryit;
tryit.send();
auto const& [name, action] = tryit.receive();
std::cout << std::quoted(name.data()) << " " << std::quoted(action.data()) << std::endl;
}
打印
1 128 10
0 128 10
"asd" "vsq"
注意
- 在C数组上使用
std :: array
可以在默认情况下为您提供复制语义 - 捍卫AccessQueue的POD功能
- 确保成员已初始化
- 确保副本安全
- 确保副本始终以NUL终止
- 请勿使用
new
或删除.为什么C ++程序员应尽量减少对"new"的使用? - 确保您的接收缓冲区大小与max_msg_size( boost进程间message_queue相匹配和叉子)
- using
std::array
over C arrays gives you copy semantics by default - guard the POD-ness of AccessQueue
- make sure the members are initialized
- make sure the copies are safe
- make sure the copies are NUL-terminated always
- Don't use
new
or delete. Why should C++ programmers minimize use of 'new'? - make sure your receive buffer size matches the max_msg_size (boost interprocess message_queue and fork)
¹共享回忆:(
这篇关于boost :: interprocess :: message_queue在第二个进程中没有收到消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!