This is mainly a question about scope and threads. Let's say we have the following struct.
struct Test
{
int number;
std::string name;
};
An instance of this struct will be used as an argument in the pthread_create function. Here is an example of what this might look like.
pthread_t tid[5];
for(int i = 0; i < 5; ++i)
{
Test test;
test.number = 5;
test.name = "test";
pthread_create(&tid[i], NULL, func, (void *)&test);
}
Is this acceptable? Since test is declared in the for's scope, that means we can only rely on it existing during a single iteration of the for loop.
When pthread_create is called, a pointer to test is given as an argument. This means that func is receiving the same pointer that is passed in to pthread_create. This means that when test goes out of scope, we can no longer rely on that pointer referring to test. If we were to create more locals, hence changing the stack, the location that the pointer points to would be overwritten by those new locals. Is this correct?
Is this acceptable?
In general, no, for the reasons you stated. Specifically, the thread's entry-function may not start executing until after the Test object has been destroyed, or the Test object might be destroyed while the thread's entry-function is still using it. Either of those possibilities will lead to undefined behavior (and a program that only works correctly "sometimes").
You need to guarantee that the data you pass to the thread remains valid for as long as the thread needs to use it. One way to do that is to allocate that Test object on the heap, and have the thread call delete on the Test-pointer when it's done using it. Alternatively, you could use a condition variable to "pause" the main thread until the child pthread signals that it is done accessing the Test on the main thread's stack, so that it is now safe for the main thread to continue execution.
If we were to create more locals, hence changing the stack, the
location that the pointer points to would be overwritten by those new
locals. Is this correct?
Yes, you understand the issue correctly.
Related
I want to know if thread1, calls a class function via passed object 'obj->fun()' and that object is deleted in the background by some other thread say thread2 what happens to function execution by thread1.
Example:
ClassA {
int functionA() {
...condition(started_execution);
int a=0;
a++;
printf(....a);
return a;
}
};
void startExecution(void *arg) {
/*casting code object A*/
A->functionA();
}
int main() {
ClassA *A = new ClassA();
pthread_create(....,startExecution,(void *)A);
....wait_for(started_execution);
delete A;//just want to know the behaviour and not join method.
}
Question: In the above scenario, A->functionA calls function functionA. If the function is executing, what will the impact of delete A on function execution since object A invoked it? functionA is not working on shared data?
If the function is executing, what will the impact of delete A on function execution since object A invoked it?
If the executing function uses this in any way, the impact would be undefined behaviour. By using this I mean access any data member or base sub object, call any member function, indirecting this or passing this to some function that would do any of those things.
Your functionA doesn't appear to use this in any way after setting the condition variable, so there would be no impact whatsoever - assuming the condition variable access itself is properly synchronised.
However, it's not a very good idea to do this, since it is not visible in the definition of functionA that no member must be accessed. It would be easy for a programmer to not follow that requirement when changing the function later.
As far as I can tell, this situation is analogous to the case of delete this; which is considered to conform to standard, but is potentially dangerous: Is delete this allowed?
A variant of
std::unique_ptr in a loop - memory leaks
In this modified question, RunSimulation() is a member method.
I would like one of the unique_ptr objects (sim) in main() to expire within main() and the other object (r) sent outside main() to free up in RunSimulation(). Would be great if you can provide a working code.
class Result { public: int n; };
class Simulation
{
public:
void RunSimulation(std::unique_ptr<Result> result) {result->n = 0;}
};
void main()
{
boost::thread_group threads;
std::unique_ptr<Result> r;
std::unique_ptr<Simulation> sim = std::make_unique<Simulation>();
for (int i = 0; i < 10; i++)
{
r = std::unique_ptr<Result>(new Result);
//Erroneous lines:
//threads.create_thread(boost::bind(&Simulation::RunSimulation, boost::ref(sim), std::move(r)));
//threads.create_thread([&] {sim->RunSimulation(std::move(r)); });
}
threads.join_all();
}
Your attempt to pass the functor created by boost::bind to create_thread fails because of the reason I explained in my answer to your previous question.
The attempt with the lambda should compile, but it has a subtle bug that will cause undefined behavior. I may have mislead you with my earlier answer, but this is the reason posting an MCVE is so important. The small snippet you posted in your previous question doesn't show how you intend to use the code.
The problem with the lambda is that it only stores a reference to the unique_ptr. You don't transfer ownership until the call to RunSimulation executes, in other words, transfer of ownership only happens after the thread execution has begun. But by that time the for loop within main may have moved on to the next iteration, causing the Result held by the unique_ptr in the previous iteration to be deleted. Dereferencing the unique_ptr within RunSimulation then causes undefined behavior.
The way around this is to transfer ownership of the unique_ptr immediately to the lambda, and then have the lambda again transfer ownership in the call to RunSimulation. This following lambda expression does what you want
[&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
}
To explain what's going on, the lambda is capturing sim by reference (&sim) and it's using C++14's lambda init capture to transfer ownership of r within main to an r that is member of the lambda (r=std::move(r)) (you can call the lambda's member r something else if you want). The lambda itself needs to be mutable because you need to have non-const access to the r data member so you can move it when calling RunSimulation.
Unfortunately, this is not the end of your problems. Calling create_thread with the above lambda still doesn't compile because according to the documentation, it requires the callable object to be copyable. Your lambda isn't copyable because it has a unique_ptr data member.
A workaround is to create a boost::thread and then add_thread it to the thread_group.
auto t = new boost::thread([&sim, r=std::move(r)] () mutable {
sim->RunSimulation(std::move(r));
});
threads.add_thread(t);
Note that I can't find any documentation on exception safety guarantees that add_thread makes. So it's possible if an exception occurs while add_thread attempts to add the new thread to the thread_group, your thread object might leak.
Live demo
Finally, I think you need to rethink your design. Presumably, the Result object is supposed to hold the simulation result. What's the point of having RunSimulation store that in Result if you cannot access that Result within main after the simulation has ended?
As I suggested in the comments of my previous answer, you should probably create a container of Results in main and pass references to the elements of those containers to RunSimulation.
If you have shared variables between a std::thread and the main thread (or any other thread for that matter), can you still access those shared variables even if you execute the thread::detach() method immediately after creating the thread?
Yes! Global, captured and passed-in variables are still accessible after calling detach().
However, if you are calling detach, it is likely that you want to return from the function that created the thread, allowing the thread object to go out of scope. If that is the case, you will have to take care that none of the locals of that function were passed to the thread either by reference or through a pointer.
You can think of detach() as a declaration that the thread does not need anything local to the creating thread.
In the following example, a thread keeps accessing an int on the stack of the starting thread after it has gone out of scope. This is undefined behaviour!
void start_thread()
{
int someInt = 5;
std::thread t([&]() {
while (true)
{
// Will print someInt (5) repeatedly until we return. Then,
// undefined behavior!
std::cout << someInt << std::endl;
}
});
t.detach();
}
Here are some possible ways to keep the rug from being swept out from under your thread:
Declare the int somewhere that will not go out of scope during the lifetime of any threads that need it (perhaps a global).
Declare shared data as a std::shared_ptr and pass that by value into the thread.
Pass by value (performing a copy) into the thread.
Pass by rvalue reference (performing a move) into the thread.
Yes. Detaching a thread just means that it cleans up after itself when it is finished and you no longer need to, nor are you allowed to, join it.
In the constructor of one of my classes I call the Windows function CreateThread as last operation. The thread is created to execute immediately and I pass the this pointer of my class as lpParameter.
In the thread procedure I cast the parameter passed back to a pointer of my class and name it pThis.
I can see that pThis points to the same memory location as the this pointer I passed when I called CreateThread. However if I look at the member variables accessed by pThis->... they all have wrong values.
I expected the value of this->member_variable used in the class to which the this pointer belongs to be the same as the one I get when writing pThis->member_variable in the thread's procedure.
If I call CreateThread in another member function (not the constructor) everything behaves correctly.
Hence the question: Is it forbidden to call the Windows function CreateThread from within the constructor of a C++ class? If yes, what is the problem?
Clarification:
1) I can confirm that the object always exists. The object gets out of scope only when the entire program ends. As I already said: calling CreateThread from some other member function does work.
2) Corrected the 'wired' typo, should have been 'weird', sorry.
Some code:
I try to post code snippets reducing things to the bare minimum while maintaining the 'faulty' parts.
class CTimerW32 : public CTimer
{
public:
CTimerW32();
~CTimerW32();
private:
static void CALLBACK TimerCallback(LPVOID lpParam, BOOLEAN bReason);
static DWORD WINAPI WaitCompletition(LPVOID lpParam);
private:
HANDLE m_hCompletitionEvent;
HANDLE m_hCompletitionThread;
bool m_bStartDeferred;
};
You can safely ignore the baseclass CTimer as it is just an abstract baseclass enabling build on different platforms.
CTimerW32::CTimerW32()
{
m_bStartDeferred= false;
m_hCompletitionEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
m_hCompletitionThread= CreateThread(NULL, 0, WaitCompletition, this, 0, NULL);
}
Here I can see that m_hCompletitionEvent is valid after the call to CreateEvent.
DWORD WINAPI CTimerW32::WaitCompletition(LPVOID lpParam)
{
CTimerW32* pThis;
DWORD dwRet;
pThis= (CTimerW32*)(lpParam);
while (true) {
// just wait for the completition event to be signaled
dwRet= WaitForSingleObject(pThis->m_hCompletitionEvent, INFINITE);
// ...
if (pThis->m_bStartDeferred) {
// ...
}
}
Here things are going wrong in the call to WaitForSingleObject. As already stated the this pointer of the object of class CTimerW32 (now pThis) still has the same value as the this pointer during thread creation. However the handle in pThis->m_hCompletitionEvent seems to be random data. It is not the value observed after the call to CreateEvent in the constructor.
Creating a thread in a constructor should not be an issue. Also, your object should be fully initialized by the initializer list before any code in the constructor is run to create the thread, so initialization probably isn't an issue.
It is likely that the object you're watching is out of scope and its destructor is called prior to you observing it in the new thread. Try creating the object dynamically with new and see if this still happens, I bet it doesn't as the object won't get destroyed when it falls out of scope.
Obviously, you should keep a pointer to this object in a higher scope so you can eventually delete it too :)
You will probably have the best luck debugging this problem with the aid of Application Verifier. If you turn on the "Basics" option for your program, it will enable PageHeap, which will fault immediately when memory gets freed. If you're stack-allocating the timer variable, you're in less luck, but it should be possible to see in the debugger if at the time you notice the corruption, the thread which created the timer is still within the function where the CTimerW32 function was declared.
Lastly, for this usecase, the Threadpool Timer APIs may work more easily, and with less resource consumption, than creating your own dedicated thread.
I have a class member functionA which creates a thread to run another functionB. FunctionB would perform some operation and stop after some time ( it is kind of fire and forget function call and the number of functionA calls and threads needed would depends on the run time result). FunctionA would be called multiple times. I realized that the pthread_create would take in pthread_t for the first parameter, and the pthread_t must be available while creating the thread. So, I could not declare it as local like below. So where could I declare the pthread_t?
void classA::functionA(int param)
{
pthread_t t; //could not declare local because functionA might return and destroy t before thread being created.
pthread_create(&t , NULL, functionB, param);
}
void functionB(int param)
{
}
Firstly, you can put your pthread_t on the stack: your functionA is fine in that respect. pthread_create stores the thread handle directly, so as soon as it returns the handle is valid. The newly created thread hasn't necessarily started executing yet, but that doesn't matter, as it won't touch that handle.
However, you need to manage your thread somehow. If you don't explicitly create it detached, then you must call pthread_join or pthread_detach on your handle. If you don't call either then you are leaking resources. If this really is a "fire and forget" thread then you should use pthread_detach to ensure that the OS cleans up when the thread finishes.
Either way, you need to ensure that the objects accessed by the thread outlive any potential accesses to them by the thread (e.g. by not destroying them until an "I don't need these objects any more" flag is set)
You can have a pthread_t variable on the stack, there is no problem with that.
Is there a reason you don't use a thread wrapper like boost::thread? It would make your life much easier. http://www.boost.org/doc/libs/1_45_0/doc/html/thread/thread_management.html
Another thing is that you can't just fire and forget a thread because once you do the object must not be destroyed before the other thread stops accessing it. In other words, the destructor of your object must make sure there are no other threads accessing the object.
I don't believe you have a problem as pthread_create() won't return before the new thread identifier has been written into t so there is no need to do new pthread_t at all. You need to check the return from pthread_create() of course though.
I would do it this way:
class classA
{
void functionA();
static void void functionB(classA* aThis);
};
void classA::functionA(int param)
{
//create thread: note that this way pthread_t can even become the class-member
}
void classA::functionB(classA* aThis)
{
classA* theThis = static_cast<classA*>(aThis);
//now you can access classA members here easily
}