我有一段代码在带有3个lambda的ROS Runloop中运行-两个用于修改标志,一个用于调用ROS Runloop,直到主题达到特定条件为止。本质上接近
bool wait_until_engine_started()
{
bool engine_started_state = false;
bool engine_started_event = false;
// Psuedocode for a subscription wrapper which invokes the below lambda
auto engine_state_checker =
[&](const EngineRosMessage::ConstPtr& msg) {
// Psuedocode for a validation function
if (engine_appears_to_be_on(msg))
{
// Modify the referenced boolean here
engine_started_state = true;
}
// Return to runloop
}
);
// Psuedocode for a subscription wrapper which invokes the below lambda
auto engine_code_checker =
[&](const DifferentEngineRosMessage::ConstPtr& msg) {
// Psuedocode for a validation function
if (engine_appears_to_be_on_via_different_method(msg))
{
// Modify the referenced boolean here
engine_started_event = true;
}
// Return to runloop
}
);
return utils::spin_until_condition([&](){
return engine_started_state && engine_started_event;
});
}
使用
bool spin_until_condition(std::function<bool()> condition)
{
while(ros::ok() && !condition())
{
ros::spinOnce();
}
return ros::ok();
}
在某些情况下,当包含与本节无关的特定代码段时,在spin_until_condition
lambda中使用了lambda时,我遇到了段错误。
在GDB中进行探测表明在我的机器上
engine_started_event
声明级别,engine_started_event
的地址为0x7fffffffc3ff
engine_code_checker
内,engine_started_event
的地址为0x7fffffffc3ff
spin_until_condition
的右值lambda中,engine_started_event
的地址最初为0x7fffffffc3ff
,但在engine_started_event = true
之后,移至0x1007fffffffc3ff
,此时发生段错误通过删除与此块无关的特定代码块,可以非常可靠地禁用此行为。更进一步,以上代码段被遍历了两次-一次在导致问题的块之前,一次在此之后,而问题仅在第二轮发生。
AFAIK-没有理由引用应该更改其地址,并且删除问题块的可靠性使我认为它是负责任的,但是鉴于布尔值和第3个lambda是堆栈分配的变量。
我正在gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.11)
上运行此命令-在gcc-7
上运行此命令不会导致段错误,这使我怀疑编译器是怎么回事。但是我一次又一次地了解到,编译器通常可以很好地完成工作,而删除代码可以消除问题的事实似乎强烈地指向了我们的代码。我现在的猜测是,无关代码中的不良内存写入会导致引用以某种方式更改。
Valgrind除了在0x1007fffffffc3ff
上进行实际的段错误访问外,也未显示任何相关内容
所以-TL; DR
答案 0 :(得分:0)
这种行为可能是堆损坏。您要删除的似乎无关的块很可能正在访问不应访问的内存。检查循环以编写数组的边界,访问已删除的内存或两次删除。
可能发生的是这段代码覆盖了lambda对象生存的内存,并最终更改了其捕获的值。