0

I am currently working through the C++ Crash Course book (https://ccc.codes/) and facing the following issue in the code on Page 295 (Listing 10-17 Unit Testing for Brake events). The following code uses assertion to assert that the BrakeCommand is published but seems to throw a segmentation fault when run.

#include <iostream>
#include <stdexcept>

...

struct BrakeCommand {
    double time_to_collision_s;
};

template<typename T>
struct AutoBrake {
    AutoBrake(const T &publish) : publish{publish}, speed_mps{}, collision_threshold_s{5} {}

    ...

    void observe(const CarDetected &cd) {
        const auto relative_velocity_mps = speed_mps - cd.velocity_mps;
        const auto time_to_collision_s = cd.distance_m / relative_velocity_mps;
        if (time_to_collision_s > 0 && time_to_collision_s <= collision_threshold_s) {
            publish(BrakeCommand{time_to_collision_s});
        }
    }

    ...

private:
    const T &publish;
    double collision_threshold_s;
    double speed_mps;
};

    ...

void alert_when_imminent() {
    int brake_commands_published{};
    AutoBrake autoBrake{
            [&](const BrakeCommand &) {
                brake_commands_published++;
            }
    };
    ...
    autoBrake.observe(CarDetected{100L, 0L});
    assert_that(brake_commands_published == 1, "brake commands published not one");
}

//Run Test
void run_test(void(*unit_test)(), const char *name) {
    try {
        unit_test();
        printf("[+] Test %s successful.\n", name);
    }
    catch (const std::exception &e) {
        printf("[-] Test failure in %s. %s.\n", name, e.what());

    }
}

int main() {
    
    run_test(alert_when_imminent, "alert when imminent");
}

It seems that referencing brake_commands_published from the publish call in Autobrake::observe seems to push the value of brake_commands_published out of scope and causes a dangling reference error. Can anyone help me understand why this happens and how to fix it?

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
Ikun
  • 197
  • 1
  • 12
  • 3
    const reference class members do not extend the lifetime of temporary objects – NathanOliver Aug 14 '23 at 01:50
  • 1
    You have dangling `publish` reference... – Jarod42 Aug 14 '23 at 01:51
  • I am a newcomer to C++ but from what I understand, if the original function creating `brake_commands_published` has not yet finished, why would the value of `brake_commands_published` go out of scope and create a dangling reference? – Ikun Aug 14 '23 at 01:52
  • @NathanOliver: unless with aggregate initialization ;-) (not the case here). – Jarod42 Aug 14 '23 at 01:53
  • @Ikun: you have code similar to `AutoBrake autoBrake{temporary()}; autoBrake.f_using_temporary_ref();` – Jarod42 Aug 14 '23 at 01:54
  • Looks like a better C++ textbook will be in order. The one that resulted in the shown code is substandard. – Sam Varshavchik Aug 14 '23 at 01:55
  • @Jarod42 I keep forgetting about that edge case. Not sure why it was allowed. – NathanOliver Aug 14 '23 at 02:00
  • @Jarod42 So if I understand correctly the lambda function assigned to `publish` is temporary and when called from `observe` is causing a dangling reference? What would be a way to resolve this? – Ikun Aug 14 '23 at 02:03
  • 1
    Store value, i.e `T publish;` instead of `const T &publish;`. – Jarod42 Aug 14 '23 at 02:06
  • @Jarod42 That seems to have fixed it, thanks alot. – Ikun Aug 14 '23 at 02:07

0 Answers0