I'm new to C and I'm trying to make the console print "after 5 seconds" after 5000 ms. Then print "insta log" immediately after the new thread's declaration.
But doing so crashes with the following error:
"Debug Error!
[PROGRAM PATH]
abort() has been called
"
This is my code:
#include <iostream>
#include <thread>
#include <Windows.h>
#include <ctime>
using namespace std;
void f() {
Sleep(5000);
cout << "after 5 seconds" << endl;
}
int main() {
cout << "starting" << endl;
// Pass f and its parameters to thread
// object constructor as
thread t(&f);
cout << "insta log" << endl;
}
I'm unsure why this is happening. I've searched around and I found a "fix" but it makes my code not behave as intended.
This is the "fix"
#include <iostream>
#include <thread>
#include <Windows.h>
#include <ctime>
using namespace std;
void f() {
Sleep(5000);
cout << "after 5 seconds" << endl;
}
int main() {
cout << "starting" << endl;
// Pass f and its parameters to thread
// object constructor as
thread t(&f);
t.join();
cout << "insta log" << endl; // doesn't print for 5 seconds
}
This removes the error message but yields the main thread for 5 seconds. Which makes my code not work as intended.
Thanks in advance, any help is appreciated!
CodePudding user response:
This removes the error message.
Yes.
but yields the main thread for 5 seconds.
This is not what is happening!
The main thread is waiting for your second thread t
to finish (slightly different to yielding).
The problem before was that the main thread was exiting the application (and you are not allowed to have other threads running after the main thread exits (this is because what happens to the children thread is highly depended on the threading implementation and they very wildly).
In the C std::thread
class they try and compensate for the above behavior by making the destructor terminate()
if the current thread leaves scope without the child thread of execution completing.
This means you usually have to call the join()
method to wait for the child to exit.
So what you usually do is 1: create a std::thread
object that does some work in the background 2: while you do some work locally. Then when you have finished, 3: you call join()
and wait for the child object to also finish (if it has already finished this does nothing). Then you can exit scope (and exit the main).
Which makes my code not work as intended.
int main()
{
// STUFF.
// Create your thread.
thread t(&f);
// Print any thing you want.
// i.e. do the work you want to do in main.
cout << "insta log" << endl;
// When you have finished.
// wait for the child to finish.
t.join();
} // now the std::thread::~thread check to make sure the
// child thread of execution is no longer running.
CodePudding user response:
If you had clicked 'retry' in that dialog you would have seen why your code died. Its right here
~thread() noexcept {
if (joinable()) {
_STD terminate();
}
}
in the MSVC implementation of std::thread. The code says that destroying a thread thats still joinable (ie is running) is illegal. I dont know if thats c defined behavior, a quick search didnt show me. Anyway when you join
the thread, you will wait till its OK to destroy it
CodePudding user response:
Functions are already passed around as pointers, use thread t(f)
instead of thread t(&f)
.
Moreover, since your main()
neither lasts longer than the thread or calls a t.join()
, the program will end before the thread finishes it's code, so that might be another reason for a crash. In fact it is probably the reason for the crash.
If you want "insta log"
to print instantly, then call t.join()
at the end of main()
. t.join()
will wait for the thread t
to end before continuing.