Home > database >  How to provoke crash with c futures and reference to local variables?
How to provoke crash with c futures and reference to local variables?

Time:11-01

I would very much like to understand Eric Niebler's warnings about c futures and dangling local references (in the section titled "The Trouble With Threads"). I, therefore, wrote a little program, repeated below:

#include <iostream>
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#define BOOST_THREAD_PROVIDES_FUTURE
#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <boost/thread/future.hpp>

void computeResult(int& i) {
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
    std::cout << i << std::endl;
    i  = 1;
}

boost::future<int> doThing() {
    int local_state{0};
    auto lam = [&]() { return computeResult(local_state); };
    auto fut = boost::async(lam);
    return fut.then([&](auto&&) { return local_state; });  // OOPS
}

int main() {
    auto fun = doThing();
    int out = fun.get();
    std::cout << out << std::endl;
}

The text states that:

If you’ve programmed with futures before, you’re probably screaming, “Nooooo!” The .then() on the last line queues up some work to run after computeResult() completes. doThing() then returns the resulting future. The trouble is, when doThing() returns, the lifetime of the State object ends, and the continuation is still referencing it. That is now a dangling reference, and will likely cause a crash.

I modified the doThing function a little bit to call computeResult asynchronously but otherwise tried to follow the examples in the text. Unfortunately, the program runs perfectly fine on my computer. Can someone kindly outline how to write a program that crashes reliably, as outlined in Eric Niebler's description?

CodePudding user response:

Like everyone says, believing that Undefined Behaviour would lead to a crash is misguided.

It's a dangerous believe, because the consequences of UB are much more dire when there is silent data corruption, deadlocks, or indeed nothing easily observable for years (until your program suddenly launches that nuclear missile).

There are tools (like asan/ubsan and valgrind/helgrind) to diagnose many cases before they cause you more pain.

Let's run your sample with GCC or Clang's -fsanitize=address,undefined options you get:

1264
AddressSanitizerAddressSanitizer:DEADLYSIGNAL
:DEADLYSIGNAL
=================================================================
==13854==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x7fc8d475b88e bp 0x613000000040 sp 0x7fc8c4cfe9b0 T1)
==13854==The signal is caused by a READ memory access.
==13854==Hint: this fault was caused by a dereference of a high value address (see register values below).  Dissassemble the provided pc to learn which register was used.
/home/sehe/custom/boost_1_77_0/boost/thread/lock_types.hpp:346:14: runtime error: member call on misaligned address 0x6120000004f1 for type 'struct mutex', which requires 8 byte alignment
0x6120000004f1: note: pointer points here
 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
              ^ 
/home/sehe/custom/boost_1_77_0/boost/thread/pthread/mutex.hpp:61:48: runtime error: member access within misaligned address 0x6120000004f1 for type 'struct mutex', which requires 8 byte alignment
0x6120000004f1: note: pointer points here
 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
              ^ 
/home/sehe/custom/boost_1_77_0/boost/thread/lock_types.hpp:331:18: runtime error: member call on misaligned address 0x6120000004f1 for type 'struct mutex', which requires 8 byte alignment
0x6120000004f1: note: pointer points here
 00 00 00  00 01 00 00 00 00 00 00  00 1e 36 00 00 01 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
              ^ 
/home/sehe/custom/boost_1_77_0/boost/thread/pthread/mutex.hpp:70:13: runtime error: member access within misaligned address 0x6120000004f1 for type 'struct mutex', which requires 8 byte alignment
0x6120000004f1: note: pointer points here
 00 00 00  00 01 00 00 00 00 00 00  00 1e 36 00 00 01 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
              ^ 
1265

(As a sidenote, the given program does cause a crash on my machine/compiler even without the sanitizers)

  • Related