Pages 295 and 296: Getting an unexpected behavior when try to capture local variable
Hello Josh.
I'm testing the book examples, and I'm stuck in chapter 10 when you describe an example that uses a local variable captured by a lambda function.
Page 295:
void alert_when_imminent() {
int brake_commands_published{};
AutoBrake auto_brake{
[&brake_commands_published](const BrakeCommand&) {
brake_commands_published++; // --> segfault
} };
--snip--
I'm intrigued about the correct way to use a local variable with lambdas. I tried to use a shared_pointer, but the var increment not work. :/
Could you help me?
I dug a little more.
Some instructions in alert_when_imminent, as the variable definition, are executed previously, of course, that the lambda function. However, It seems that stack unwinds the brake_commands_published before lambda does the increment, resulting in a segfault.
I'm not familiar with lambdas, and I don't know if that is made by the GCC compiler when doing the instruction scheduling, or it is the natural behavior of the lambdas. But the failure does not happen If I set brake_commands_published as a global variable.
I'm curious about how to handle this. :)
Hi, @carpajr! Thanks for your ticket. Could you please provide me a full code listing? Or even better a link to a https://wandbox.org program?
Hi, @JLospinoso! Sorry for delay.
I tried to reproduce the issue using wandbox, but there works fine. However, I'm using GCC 7.4.0 (Ubuntu 18.04.1) and finding some trick optimization that CLION is doing. Because when I run the same code*, the code has a segmentation fault.
[+] Test initial speed is 0 successful.
[+] Test initial sensivity is 5 successful.
[+] Test sensitivity greater than 1 successful.
[+] Test speed is saved successful.
Segmentation fault
- https://wandbox.org/permlink/6og4hnFTFbMmFXzv
Thanks for posting, @carpajr!
I think this might be some sort of CLion bug. I believe the issue is that const reference publish in AutoBrake doesn't have the proper lifetime. When you bind a temporary (like the lambda on line 137) to a const reference, it should work out as you'd expect (see https://blog.galowicz.de/2016/03/23/const_reference_to_temporary_object/). I'll keep investigating.
In the closing commit for errata, I can't find any change regarding chapter 10. Is there a follow-up on this issue? I am also observing it, not with CLion, but with plain g++ 9.3.0 on Ubuntu 20.04.3 LTS.
A simple solution to this is below. And my environment is g++ 7.5.0 with -std=c++17 option.
void alert_when_imminent() {
int brake_commands_published{};
auto foo = [&brake_commands_published](const BrakeCommand &) {
brake_commands_published++;
};
AutoBrake auto_brake{foo};
// -- snip --
}
IMHO, lambda expression in AutoBrake object can't capture out of object's scope.
I'll leave this open - honestly I'm not seeing the lifetime issue here. If someone has an explanation I'll post an errata otherwise leaving as-is for now.