A parent thread should always wait until child threads have terminated. To do this, use thread::join - C++ Reference
std::thread t1(t1_exec, main_observer);
cout << "In main thread" << endl;
cout << "Child thread has terminated" << endl;
But the most probable reason that your program crashes is that you call
Calling this function destroys all objects with static duration: A program with multiple threads running shall not call exit (see quick_exit for a similar function that does not affect static objects).