0

A thread is created with a member function, but the related object reaches the end of scope and distroyed. I found it strange that the thread continues without error. I guess it's pure luck, but I cannot prove it.

#include <iostream>
#include <thread>
#include <chrono>

using namespace std::chrono_literals;
using namespace std;

struct Base {
    int N = 10;
    Base(int _N) : N(_N) {
        cout << "Base Ctor\n";
    }

    virtual ~Base(){
        cout << "Base Dtor\n";
    }

    void counter() {
        for ( auto i{0}; i < N; ++i ) {
            this_thread::sleep_for( 1s );
            cout << "step: " << i << " / " << N << endl;
        }
    }
};

int main() {
    {
        // limit the scope of b
        Base b(10);
        thread th( &Base::counter, std::ref(b) );
        th.detach();

        std::this_thread::sleep_for( 5s );
        // destruct b
    }
    std::this_thread::sleep_for( 10s );
    return 0;
}

I got the following result:

Base Ctor
step: 0 / 10
step: 1 / 10
step: 2 / 10
step: 3 / 10
Base Dtor
step: 4 / 10
step: 5 / 10
step: 6 / 10
step: 7 / 10
step: 8 / 10
step: 9 / 10
Jónás Balázs
  • 781
  • 10
  • 24
  • 5
    You have undefined behavior. That can be anything from "working fine" to activating skynet and dooming us all. – NathanOliver Jul 31 '18 at 13:29
  • 1
    `b` is destructed, of course, not your thread, since it is a local variable in a block that has ended. And yes, it is just luck probably. Probably, no one overridden the bytes in the stack were `b` was stored – SomethingSomething Jul 31 '18 at 13:32
  • "I found it strange that the thread continues without error." Welcome to UB - compiler is obligated to produce correct executable for correct code, its is NOT obligated to produce executable which would mandatory fail for incorrect code. Fill the difference. – Slava Jul 31 '18 at 13:35
  • 1
    @NathanOliver I was going to upvote your comment, but [I disagree with the skynet part](https://youtu.be/yG1OZ69H_-o?t=56). – Borgleader Jul 31 '18 at 13:36
  • 1
    I think it would be helpful to have generic question "C++ I have code with UB why program does not fail?" and mark one like this as duplicate, such questions appear quite often – Slava Jul 31 '18 at 13:39
  • @Borgleader That is a good talk. – NathanOliver Jul 31 '18 at 13:41
  • 1
    P.S.: There's a name for what you have created. It's called a _[dangling reference](https://en.wikipedia.org/wiki/Dangling_pointer)_. – Solomon Slow Jul 31 '18 at 13:56

0 Answers0