1

Reason why somebody would be interested in

  //...
 new std::thread (func,arg1,arg2);

}

is that std::thread destructor(unlike boost::thread) kills the thread. func finishes is some time. My question is this safe in cases:

Case 1: lets say that function takes arg1, arg2 by value.
Case 2: lets say that function takes arg1, arg2 by reference-this sounds bad if you ask me, because I presume that at the end of the scope where thread is created arg1 and arg2 will be cleared by their destructors.

BTW is std::thread destructor(that is AFAIK called when func finishes) smart enough to clear all the resources used by thread? I mean if I create 1M threads(ofc not at the same time) with new and all of them finish, have I leaked anything permanently?

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 3
    You're not leaking a thread there, you still have a pointer to it after that block ends. So I think your question title is a bit misleading and doesn't really reflect your question. – Mat Sep 13 '11 at 18:31

3 Answers3

11

An std::thread object represents a thread, it is not a "real" thread, that is a concept managed by the OS.

Therefore, here you're leaking a std::thread object because you don't delete it. The destructor is never called. But the thread it was representing will end when it's instructions will end, like any thread.

If the destructor was called before the end of the instructions, for example if you would have created that object on the stack and there was a lot of things to do in this new thread, then the destructor call would have triggered std::terminate(). You need to call detach() to allow the thread to continue after the std::thread instance is destroyed.

That way, you have to explicitely say if you want or not this thread to end when the std::thread instance is destroyed : if you want it to continue, call detach(); if you want to wait for it to end, call join().

So in your case you leak memory but the thread should continue as the std::thread object lives "forever" because you lost any way to control it.

Community
  • 1
  • 1
Klaim
  • 67,274
  • 36
  • 133
  • 188
  • nice answer. Is there any way to do what I want. To basically safely run function in new thread without joining? – NoSenseEtAl Sep 13 '11 at 20:49
  • by safely I mean that it cleans its scope(calls destructors) and cleans itself. – NoSenseEtAl Sep 13 '11 at 21:24
  • 1
    @NoSense: You will have to build a system within that thread to be able to "run function" in it. Remember: a thread is a simple, low-level construct. It executes the function you told it, and will end when it reaches the end of that function. If you want to do what you're talking about, you will need to make the thread function look for commands to execute, wait until you have provided them from the other thread, and then execute them. When it finishes with those commands, it waits until you give it more. All of that logic must be written by you (or you use a library). – Nicol Bolas Sep 14 '11 at 00:22
  • what about if function is : try{//work} catch(...){//do nothing, except completed=false}, does that make it run and forget(ofc you need to check value of the completed var if you want to use data modified by func.). – NoSenseEtAl Sep 14 '11 at 10:09
  • It can be interesting, in those cases, to have a sort of RAII thread than can be derived from std::thread, whose destructor calls join(). This will make the "thread destroyer" to wait for their completion. – Emilio Garavaglia Sep 14 '11 at 12:39
  • 1
    @NoSenseEtAl You can just `detach()` the thread (it will be left to run on its own), or you can use `std::async`, and avoid `std::thread` which is a finicky low-level construct that will std::terminate at the slightest provokation. – R. Martinho Fernandes Sep 14 '11 at 15:32
1

This is not OK according to the final text. Specifically, the destructor of a thread that has been neither joined nor detached will call std::terminate.

std::thread destructor is not called when the callback returns, but when the thread object goes out of scope, just like any other object. So, a new'd thread that is never delete'd will never be destructed, leaking any associated state (and things potentially going horribly wrong if/when the program terminates with any extra threads still running...)

To answer your question about lifetimes, std::thread is like std::bind: it stores copies of its arguments and passes those copies to the callback, regardless of whether the callback takes its arguments by value or by reference. You must explicitly wrap arguments with std::ref to get reference semantics. In this case, as usual, it's up to you to ensure that no dangling references occur (for instance by calling thread::join() before any referenced variables go out of scope.)

JohannesD
  • 13,802
  • 1
  • 38
  • 30
  • 1
    But nobody is deleting the pointer being allocated here, so how would the destructor run in the first place? – ildjarn Sep 13 '11 at 19:15
1

BTW is std::thread destructor(that is AFAIK called when func finishes) smart enough to clear all the resources used by thread? I mean if I create 1M threads(ofc not at the same time) with new and all of them finish, have I leaked anything permanently?

Normally, the destructor is called automatically when an object on the stack goes out of scope (or during stack unwinding when an exception has been caught). Since the thread object is allocated on the heap using new the destructor will not be called automatically, some code needs to delete the object to invoke its destructor. In other words, thread's destructor is not called when func() finishes.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271