【发布时间】:2020-08-06 22:22:52
【问题描述】:
我不完全确定如何最好地为这个问题命名,因为我不完全确定问题的本质是什么(我猜“如何修复段错误”不是一个好标题)。
情况是,我写了这段代码:
template <typename T> class LatchedSubscriber {
private:
ros::Subscriber sub;
std::shared_ptr<T> last_received_msg;
std::shared_ptr<std::mutex> mutex;
int test;
void callback(T msg) {
std::shared_ptr<std::mutex> thread_local_mutex = mutex;
std::shared_ptr<T> thread_local_msg = last_received_msg;
if (!thread_local_mutex) {
ROS_INFO("Mutex pointer is null in callback");
}
if (!thread_local_msg) {
ROS_INFO("lrm: pointer is null in callback");
}
ROS_INFO("Test is %d", test);
std::lock_guard<std::mutex> guard(*thread_local_mutex);
*thread_local_msg = msg;
}
public:
LatchedSubscriber() {
last_received_msg = std::make_shared<T>();
mutex = std::make_shared<std::mutex>();
test = 42;
if (!mutex) {
ROS_INFO("Mutex pointer is null in constructor");
}
else {
ROS_INFO("Mutex pointer is not null in constructor");
}
}
void start(ros::NodeHandle &nh, const std::string &topic) {
sub = nh.subscribe(topic, 1000, &LatchedSubscriber<T>::callback, this);
}
T get_last_msg() {
std::lock_guard<std::mutex> guard(*mutex);
return *last_received_msg;
}
};
本质上它正在做的是订阅一个主题(频道),这意味着每次消息到达时都会调用一个回调函数。该类的工作是存储最后收到的消息,以便该类的用户可以随时访问它。
在构造函数中,我为消息分配了一个 shared_ptr,并为一个互斥锁分配了对这个消息的访问。这里使用堆内存的原因是LatchedSubscriber 可以被复制并且仍然可以读取相同的锁存消息。 (Subscriber 已经实现了这种行为,复制它不会做任何事情,除了一旦最后一个实例超出范围,回调就会停止调用)。
问题基本上是代码段错误。我很确定这是因为我的共享指针在回调函数中变为null,尽管在构造函数中不是 null。
ROS_INFO 调用 print:
Mutex pointer is not null in constructor
Mutex pointer is null in callback
lrm: pointer is null in callback
Test is 42
我不明白这怎么会发生。我想我对共享指针、ros 主题订阅或两者都有误解。
我做过的事情:
- 起初我在构造函数中进行了订阅调用。我认为在构造函数返回之前将
this指针指向另一个线程可能很糟糕,所以我将它移到了start函数中,该函数在构造对象后调用。 - 看来
shared_ptrs 的线程安全有很多方面。起初我在回调中直接使用了mutex和last_received_msg。现在我已将它们复制到局部变量中,希望这会有所帮助。但这似乎没有什么不同。 - 我添加了一个局部整数变量。我可以从回调中读取我在构造函数中分配给这个变量的整数。只是一个健全性检查,以确保回调实际上是在我的构造函数创建的实例上调用的。
【问题讨论】:
-
我想重现您的问题。您能否制作一个minimal reproducible example,我可以将其复制并粘贴到
foo.cpp文件中,编译并自己查看问题?我很确定如果我尝试编写自己的代码来重现我不会放入不当行为的问题。
标签: c++ callback thread-safety smart-pointers ros