[RESOLVED Thanks] when is the destructor called ?
Quick question
When is a destructor called ?
Code:
ThreadManager::~ThreadManager()
{
CloseHandle(m_hThread);
};
Let's say this was in my code ?
Is the destructor called if this object goes out of scope ?
Example
void foo()
{
ThreadManager t ;
};
Is the destructor called when the scope has ended ?
Is there a way to call the destructor explicitly ?
Is it just as simple as delete t;
Thanks
Stev
Re: when is the destructor called ?
Quote:
Originally Posted by stephenprogrammer07
Quick question
When is a destructor called ?
When an object is destroyed.
Quote:
Is the destructor called if this object goes out of scope ?
Yes.
Quote:
Is there a way to call the destructor explicitly ?
Why? The object is automatically destroyed, so all you would be doing is destroying the same thing twice, causing program corruption.
Quote:
Is it just as simple as delete t;
You only call "delete" on objects that were created with "new".
http://www.parashift.com/c++-faq-lite/dtors.html
Regards,
Paul McKenzie
Re: when is the destructor called ?
yes the destructor is called whenever the variable goes out of scope, as in
Code:
#include <iostream>
using namespace std;
class one
{
int* a;
public:
one();
~one();
};
one::one()
{
a = new int;
*a = 5;
}
one::~one()
{
cout << "destructer called\n";
delete a;
}
int main()
{
{
one cur;
}
system("pause");
return 0;
}
shows you how it is called, you need a destructor to return stuff to the heap, it is called when the program exits unless the variable goes out of scope before hand
Re: when is the destructor called ?
You're right, the destructor is called when the object goes out of scope. However this is only for stack objects (objects that aren't created with new). For heap objects (objects that ARE created with new) the destructor is called when you delete the object.
To explicitly call a destructor somewhat removes the purpose of the destructor, since the idea behind having a destructor is that it is automatically called when the object is destroyed.
If you want to destroy an object before it goes out of scope, you can use your own destroy member function:
Code:
class Bla{
void CleanUp(); //the "destructor"
};
When you want to destroy the object, you call CleanUp(). If you want CleanUp() to automatically be called when the object goes out of scope or is deleted, call it from the destructor:
Code:
Bla::~Bla(){
CleanUp();
}
Hope this helps.
Re: when is the destructor called ?
Thanks I passed around some rep points for those answers.
Now I have something to add to this mix.
Here's my code
Code:
int main()
{
ThreadManager tmanager;
while(true)
{
if(tmanager.isThreadFinishedStatus() )
{
tmanager.launchThread(&threadManager);
}
}
}
As you can see here the ThreadManager never goes out of scope because this is an infinite while loop.
yet I put a print statement at the destructor and the destructor is called sure enough after the ThreadFunc finish running.
Isn't that something.
So since the destructor is called when my while loop executes tmanager.lanchThread(&threadManager); again, the application crashes because the destructor was called - even though the object did not go out of scope.
Any explanations on why destructor is called and app does not go out of scope ???
Thanks in advance
stev
Below is my ThreadManager code
Code:
ThreadManager::ThreadManager()
{
m_dwThreadID = 0 ;
m_hThread = 0 ;
threadStatus = true;
};
ThreadManager::~ThreadManager()
{
CloseHandle(m_hThread);
prinf("aha destructor does call before going out of scope " ) ;
};
bool ThreadManager::hasThreadReturned()
{
return threadStatus;
};
void ThreadManager::setThreadFinishedStatus(bool s )
{
if(s)
{
printf("\nThreadManager::setThreadFinishedStatus set to
true\n");
}else
printf("\nThreadManager::setThreadFinishedStatus set to
false\n");
threadStatus = s;
};
bool ThreadManager::launchThread(ThreadManager *whatever)
{
m_hThread = CreateThread(0,
0,
ThreadFunc,
(void *)whatever,
0,
&m_dwThreadID);
if(!m_hThread)
{
return false;
}
return true;
};
HANDLE ThreadManager::TheHandle(void) const { return m_hThread;
};
DWORD WINAPI ThreadManager::ThreadFunc(LPVOID pvParam)
{
Speech sp ;
ThreadManager* t = (ThreadManager*) pvParam;
t->setThreadFinishedStatus(false );
sp.Create("this is a sample param passed in") ;
::WaitForSingleObject(sp.TheHandle(), INFINITE );
t->setThreadFinishedStatus(true );
};
Speech sp is another Thread that takes bit of time to run.
Re: when is the destructor called ?
First, RAII and other design patterns that depend upon a strong constructor/destructor cycle would utterly fail if a destructor is called for any other reasons that an object's deletion (falling out of scope, delete, etc).
Under normal circumstances, it doesn't happen - destructors aren't called outside the described circumstance - that is, since you're getting a 'destructor message' even though you say the execution point is still inside the while loop, something else is responsible.
Can you produce a stack trace at that moment? It would be most instructive.
I have encountered situations where stack corruptions happen to be such that a function is called that should not be.
RESOLVED: when is the destructor called ?
@JVene
I don't know how to do a stack trace.
I'll have to figure out how to produce a stacktrace in c++.
I'm studying this article on the topic http://www.ddj.com/184405270?pgno=1
Is that a good way or do you have another way to get the stack trace ? I'm using Dev C++.
----------------------------------
Additionally, I conducted a few tests.
1. I made 2 very simple thread classes demonstrate that in truth one Thread , launching another Thread who's destructor is called will not automatically call the launching Threads destructor. I confirmed that.
2. So I tested my own code a bit more. For some reason when my thread simply instantiates my Speech class "Speech sp; in DWORD WINAPI ThreadFunc " as soon as sp goes out of Scope (meaning DWORD WINAPI ThreadFunc is finished), it calls Speech's destructor as expected but for some reason it also calls the destructor of the Launching thread which is not supposed to be called.
If I comment out Speech sp , the launching Thread's destructor is not calle.d everything works as expected
So that's where I am with it .
UPDATE:
WOOPS Never mind .
Now I see why the Launching Thread's destructor was called.
It turns out that my Speech class had as a private member The Launching Thread class.
So naturally when the speech class went out of scope it also called the destructor on the private member. So I was confused a by that.
The launching Thread's destructor was not really being called.
The private member of the speech was called.
NEVER MIND I'VE GOT IT PROBLEM RESOLVED.
Stephen
Re: RESOLVED: when is the destructor called ?
Quote:
Originally Posted by stephenprogrammer07
NEVER MIND I'VE GOT IT PROBLEM RESOLVED.
I take it that the race conditions, the busy-wait loop and the inability of the program to terminate cleanly are not an issue.
Re: [RESOLVED Thanks] when is the destructor called ?
Quote:
Originally Posted by stephenprogrammer07
Quick question
When is a destructor called ?
Code:
ThreadManager::~ThreadManager()
{
CloseHandle(m_hThread);
};
Let's say this was in my code.
Is the destructor called if this object goes out of scope ?
Yes it will.
Quote:
Example
Code:
void foo()
{
ThreadManager t ;
}
Is the destructor called when the scope has ended ?
In this case it will indeed be. Therefore you may have to ensure that CloseHandle is a valid call here - that m_hThread requires closing.
Quote:
Is there a way to call the destructor explicitly ?
Yes, calling ~ThreadManager() is allowed but should be used only when the object was created with placement-new. Placement-new is a special way to create an object whereby the constructor is called but no memory is allocated. Instead you indicate where to construct the object. It is often done in conjunction with memory-pooling. std::vector uses it as well because here you create multiple objects in a contiguous memory block.
Quote:
Is it just as simple as delete t;
That will invoke ~ThreadManager but should be called only on a pointer created with regular new. It will also release the memory.
Re: [RESOLVED Thanks] when is the destructor called ?
Quote:
Originally Posted by stephenprogrammer07
Quick question
When is a destructor called ?
Code:
ThreadManager::~ThreadManager()
{
CloseHandle(m_hThread);
};
Let's say this was in my code ?
Is the destructor called if this object goes out of scope ?
Example
void foo()
{
ThreadManager t ;
};
Is the destructor called when the scope has ended ?
Is there a way to call the destructor explicitly ?
Is it just as simple as delete t;
Thanks
Stev
If the class of an object has a destructor, C++ guarantees that the destructor is called when the object dies. A local (auto) object dies at the close of the block ({...}) in which it was created (that is, when it is conceptually popped from the runtime stack). An unbound temporary object dies at the end of the outermost expression in which the temporary was generated (often this is at the next ; ). A member object dies when its containing object dies. An array element dies when its array dies. An object allocated via new (dynamically) dies when the object is deleted. With a static object, death occurs sometime after main() finishes.
Everything but dynamically allocated objects (that is, local objects, temporary objects, member objects, static objects, and array elements) are destructed in the reverse order of construction: first constructed is last destructed.
Re: RESOLVED: when is the destructor called ?
Quote:
Originally Posted by googler
I take it that the race conditions, the busy-wait loop and the inability of the program to terminate cleanly are not an issue.
thanks everyone points given all around
@googler
what is the alternative to the busy wait that you are suggesting ?
Re: RESOLVED: when is the destructor called ?
Quote:
Originally Posted by stephenprogrammer07
what is the alternative to the busy wait that you are suggesting ?
In the main loop, use WaitForSingleObject() to wait on the thread handle. A wait on a thread handle terminates when the thread terminates and doesn't take up CPU cycles.
The code #5 also has a pretty serious race condition, because the flag threadStatus is set to false by the newly launched thread. That means the loop in main can execute an arbitrary number of iterations before the new thread sets the flag to false, and each iteration launches another thread before the first thread even starts. Each time a new thread is launched like this, it overwrites the thread handle thereby orphaning the previous threads it launched and leaving an unclosed handle.
Bottom line is that you shouldn't use a boolean to signal termination of a thread. The best thing to do is wait on the thread handle. A slightly less attractive solution is for the thread to use an Event object to signal its termination right before it exits, and then have main wait on the Event.
The final problem is that there is no way to signal main to exit its loop. This means it can only be terminated by killing its thread or the entire process (from another thread.) Killing the entire process isn't so bad because Windows cleans up the mess you left behind, but killing threads with TerminateThread (as opposed to letting the thread exit) generally leaves behind some memory and resource leaks.
It's sometimes necessary to kill threads or processes, but when you design the program, you should generally design a way to get each thread to exit gracefully. In your code there is no way for main to exit gracefully.
Re: when is the destructor called ?
Quote:
Originally Posted by googler
In the main loop, use WaitForSingleObject() to wait on the thread handle. A wait on a thread handle terminates when the thread terminates and doesn't take up CPU cycles.
My application has a GUI (code #5 is just stripped down). My goal was to provide onscreen animation and user interaction with the GUI while this thread is running.
If I used WaitForSingleObject() in the main loop, my GUI would freeze until the thread returned. I tested it to confirm that.
The reason that I created a new thread which launches the thread of interest was with the goal of maintaining the GUI interactivity.
So it doesn't seem that WaitForSingleObject() in main loop would work for my purpose unless it canwork otherwise.
Quote:
That means the loop in main can execute an arbitrary number of iterations before the new thread sets the flag to false,
making the main loop ::Sleep(10) after the launch is a crude way to fix that problem . But I admit it's a crude way to prevent race conditions.
my app is a game which normally has a indefinite while loop until the player ends the game. I use the while loop to mimic the game loop.
But if this were a normal application, I guess I would have to try something like the observer pattern or figure out how to use mutex and locks to block all threads creating new code until the other thread drops the lock.
Re: when is the destructor called ?
Quote:
Originally Posted by stephenprogrammer07
My application has a GUI (code #5 is just stripped down). My goal was to provide onscreen animation and user interaction with the GUI while this thread is running.
There are two more reasonable ways to combine a GUI message loop with waiting for background threads to finish
1) Have main execute a standard message loop. Have the background thread post a special user-defined Window message to the GUI thread (with PostMesssage) right before it terminates. Receipt of this message is the signal that the background thread is complete. With this approach you don't need any additional synchronization objects.
2) Use MsgWaitForMultipleObjects/MsgWaitForMultipleObjectsEx. This is a general mechanism for combining a GUI message loop with waiting on any number of kernel handles of any kind. The wait completes when a GUI message is ready to process or any of the handles is signalled. The program can tell from the return value why the wait completed, handle the event that caused the completion (be it a GUI message or thread terminating) and then loop to another call to the same wait function. The message loop will be terminated in response to the usual WM_QUIT message.
Re: when is the destructor called ?
would you be willing to provide a code sample of each ? .
And just to confirm - those solutions will not block the main thread until they are finished right ?
Stephen