This question already has answers here:
Memory deallocation and exceptions
(4 answers)
Closed 9 years ago.
When an exception is thrown, then the block where it is thrown is unwinded from stack:
int main ()
{
try
{
Object x; // doesn't throw
Object y; // throws
cout << "wonderful";
}
catch (...)
{
cout << "fail";
}
}
When Object allocates on construction memory on heap and deallocates it properly on destruction, then there should be no memory leak, because stack unwinding calls destructor of x (not of y, but Object guarantees, that when constructor failing, then no memory leak). As far all right, isn't it?
Let's go into depth:
int main ()
{
Object x; // doesn't throw
double *d = new double[256*256*256]; // doesn't throw
Object y; // throws
cout << "wonderful";
delete[] d;
}
Because of good education, I want to clean my trash up by myself, and not let do it the OS. I know, that every modern OS deletes by itself heap memory of a program which terminates unexpected (or expected, but no explicit deallocation). So in the upper case, the deallocation of d would do my OS, but x would be still properly deallocating its memory (because of stack unwinding and destructor call) before OS would do it, right?
What about that:
#include <cstdlib>
int main ()
{
Object x; // doesn't throw
try { Object y; } // throws
catch (...) { cout << "fail"; exit(EXIT_FAILURE); }
cout << "working and working...";
cin.get();
}
Is the destructor of x called before exit gives control back to OS?
And more in depth:
void Object::be_stupid ()
{
Object a; // doesn't throw
try { Object b; }// throws
catch (...) { exit(EXIT_FAILURE); }
}
void main ()
{
Object x; // doesn't throw
try { x.be_stupid(); } // exits program
}
Is the constructor of x called before exit gives control back to OS? If yes, then exit "unwinds" all surrounding stacks including main(), right?
Ok, got it thanks to polkadotcadaver: never use exit(), propagate exceptions until main() and do there a simple return - all stack Objects will be deallocated by their own destructor before OS takes control.
Related
I would like my C++ code to stop running with proper object cleanup if a certain condition is met; in a constructor of a class.
class A {
public:
int somevar;
void fun() {
// something
}
};
class B {
public:
B() {
int possibility;
// some work
if (possibility == 1) {
// I want to end the program here
kill code;
}
}
};
int main() {
A a;
B b;
return 0;
}
How can I terminate my code at that point doing proper cleanup. It's known that, std::exit does not perform any sort of stack unwinding, and no alive object on the stack will call its respective destructor to perform cleanup. So std::exit is not a good idea.
You should throw an exception, when the constructor fails, like this:
B() {
if(somethingBadHappened)
{
throw myException();
}
}
Be sure to catch exceptions in main() and all thread entry functions.
Read more in Throwing exceptions from constructors. Read about Stack unwinding in How can I handle a destructor that fails.
It is not possible to perform just from a constructor. If you throw an exception then applications need to set up a proper exception handling code at entry points, because if you just thrown an exception that won't be handled then compiler is allowed to skip stack unwinding and cleanup.
If you don't want to use use exceptions, you can have an init method in class B that returns a return code:
class B {
public:
B(/*parameters that will be used by init*/) : ...
int init(); // actually initialize instance and return non 0 upon failure
}
I am well aware of the fact that one should not throw any exception in destructor.
But as a part of making my grip on this concept,I coded this example :-
#include <iostream>
class A {
private:
int i;
public:
A() { i = 10; }
~A() { throw 30; }
};
int main(){
try{
A();
throw 10;
}
catch (int i) {
std::cout << i << std::endl;
std::cout << "exception caught" << std::endl;
}
}
As per my understanding, this program should be terminated by calling std::terminate() as there will be two exceptions at the same time. But, this program is giving the following output:-
30
exception caught
Can anyone please explain me the logic behind this as to why this is not terminating?
std::terminate will be called if an exception is thrown during stack unwinding. That means that if an exception is called while another exception is being handled, then std::terminate will be called.
In your example, that doesn't happen - A(); will construct and immediately destroy an instance of A. The throw 30 will then be caught correctly.
Changing your code to:
int main(){
try{
A a; // begin `a` lifetime
throw 10; // | throw #0
// | end `a` lifetime
// throw #1
}
catch(int i){
cout<<i<<endl;
cout<<"exception caught"<<endl;
}
}
will guarantee that std::terminate will be called. In this case, a will be destroyed and will throw while another exception is being handled.
live coliru example
Additional information:
cppreference/Destructors/Exceptions
StackOverflow: "throwing exceptions out of a destructor"
Note that in C++11 and above, your code snippet will call std::terminate and provide you a warning:
main.cpp: In destructor ‘A::~A()’:
main.cpp:16:15: warning: throw will always call terminate()
[-Wterminate]
throw 30;
^~
main.cpp:16:15: note: in C++11 destructors default to noexcept
terminate called after throwing an instance of 'int'
bash: line 7: 1505 Aborted (core dumped) ./a.out
As seen in the compiler output, since C++11 destructors are implicitly noexcept(true). If you want to prevent this behavior, you can simply mark them as noexcept(false). Example:
~A() noexcept(false)
{
throw 30;
}
live example on coliru
In your example, A() construct a temporary variable for A then destructs it immediately. Thus throw 10; is never executed.
The throw statement taking place is in the destructor for A. When executing A::~A(), the program is not unwinding (i.e. cleaning up state from an exception) at that point. See "Destructors that throw" for example.
Is the allocated memory managed by a smart pointer guaranteed to be freed up in event of an exception, such as below?
#include <memory>
void test( std::shared_ptr<int> sptr )
{
throw "exception";
}
int main()
{
std::shared_ptr<int> ptr( new int(1) );
test( ptr );
return 0;
}
I tried executing the code, putting breakpoint at shared_ptr destructor but I did not see it getting called. I think the memory should be cleaned up by itself. Am I right, or won't it be cleaned up?
The language standard states that:
If no matching handler is found, the function std::terminate() is
called; whether or not the stack is unwound before this call to
std::terminate() is implementation-defined
So your program isn't guaranteed to clean up after itself, but most (if not all) modern operating systems will do it post-mortem.
Had you caught the exception, the shared_ptr's instance would've been destroyed properly, ensuring no leaks.
Take better example for understanding:
#include <memory>
#include <windows.h>
using namespace std;
class A
{
public:
A()
{
cout << "Constructor" << endl;
}
~A()
{
cout << "destructor" << endl;
}
};
void test(std::shared_ptr<A> sptr)
{
throw "exception";
}
void function()
{
std::shared_ptr<A> ptr(new A);
test(ptr);
}
int main()
{
function();
Sleep(5000);
}
Before Program crash only one constructor gets called which shows it does not do destruction.
But if we do debugging in visual studio and say continue after exception then even destructor gets called.
I examined about stack unwinding on thread procedure in win32 environment.
My test code is the following.
class Dummy
{
public:
Dummy() { wcout << L"dummy ctor" << endl; }
~Dummy() { wcout << L"dummy dtor" << endl; }
};
void InnerFunc()
{
Dummy dm;
while(1)
{
char *buf = new char[100000000];
}
}
unsigned WINAPI ThreadFunc(void *arg)
{
Dummy dm;
try
{
InnerFunc();
}
catch(bad_alloc e)
{
wcout << e.what() << endl;
}
_endthreadex(0);
return 0;
}
void OuterFunc()
{
Dummy dm;
HANDLE hModule;
hModule = (HANDLE)_beginthreadex(0, 0, ThreadFunc, 0, 0, 0);
WaitForSingleObject(hModule, INFINITE);
CloseHandle(hModule);
}
int _tmain(int argc, _TCHAR* argv[])
{
OuterFunc();
wcout << e.what() << endl;
return 0;
}
Output result:
dummy ctor
dummy ctor
dummy ctor
dummy dtor
bad allocation
dummy dtor
As you know, an output of constructor and destructor is not paired. I think that _endthreadex() makes the thread handle be signaled and skips stack unwinding of the thread.
When I tested again without _endthreadex(), I was able to get a result I expected.
In this case, if I need stack unwinding on thread, shouldn't I use _endthreadex() in thread procedure?
I would guess the destructor is never called for the instance created in ThreadFunc. However, you should add a way to distinguish each constructor and destructor call to be sure.
Assuming that's what's happening, it seems pretty clear that endthreadex terminates the thread immediately without cleaning up the stack. The docs explicitly state that endthreadex is called when ThreadFunc returns, so why bother calling it explicitly here?
This is definitely a case where I'd use boost::thread instead. It will do the right thing in terms of thread creation and cleanup without making you worry about the win32-specific details.
Your problem is:
while(1)
{
char *buf = new char[100000000];
}
You have created a memory leak, on each iteration you create a new object losing any reference to the old object.
Stack Unwinding, clears off all the local objects in that scope,
Dummy dm;
is a object allocated on local storage inside InnerFunc(), Stack Unwinding rightly destroys this object and the single destructor call trace you see is due to this.
Stack Unwinding does not explicitly deallocate the dynamic memory. Each pointer allocated with new[] will have to be explicitly deallocated by calling a delete [] on the same address.
I don't see how it is related to any of the Windows thread functions(I am not much in to windows) but as I already stated you have a problem there.
Solution:
The simple solution to handling cleanups during exceptions is RAII.
You should use a Smart pointer to wrap your raw pointer and then the Smart pointer ensures that your object memory gets appropriately deallocated once the scope ends.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
What happens when we throw from a destructor? I know that it causes terminate() to be called, and memory is indeed freed and the destructor is called, but, is this before or after throw is called from foo? Perhaps the issue here is that throw is used while the stack is unwinding that is the problem.
Is this before or after throw is called from foo?
This is what is happening:
foo() is called
An object a of type A is created on the stack
The next statement throws
Now, the dtor for a is called, which throws another exception
std::terminate is called -- which is nothing but abandoning the exception handling mechanism:
From C++0x draft:
15.5.1 The std::terminate() function
1 In the following situations exception
handling must be abandoned for less
subtle error handling techniques:
[...]
— when the destruction of
an object during stack unwinding
(15.2) exits using an exception, or
2 In such cases, std::terminate() is
called (18.7.3). In the situation
where no matching handler is found, it
is implementation-defined whether or
not the stack is unwound before
std::terminate() is called. In all
other situations, the stack shall not
be unwound before std::terminate() is
called. An implementation is not
permitted to finish stack unwinding
prematurely based on a determination
that the unwind process will
eventually cause a call to
std::terminate().
Note: Emphasis mine
Here's what happens in g++:
#include <stdio.h>
class A {
public:
~A()
{
fprintf(stderr, "in ~A\n");
throw "error";
}
};
void foo()
{
A a;
fprintf(stderr, "in foo\n");
throw "error";
}
int main()
{
try {
foo();
}
catch (const char*) {
return 1;
}
return 0;
}
[~/ecc/ellcc/ecc] main% ./a.out
in foo
in ~A
terminate called after throwing an instance of 'char const*'
Abort
[~/ecc/ellcc/ecc] main%
As you can see, the throw in foo happens first, then the throw in ~A causes the error.
You got is slightly wrong and that's why you don't understand it. You see, throw in destructor is not causing teriminate() function to be called, it is a bad practice, but it is not fatal for program execution. What is fatal is that some code throws while there's still active exception. C++ can't decide what exception to propagate further, new one or old one and it can't propagate them both. It is considered fatal for program execution and that's why terminate is called.
So, you see, without throw in foo, terminate wouldn't be called but there will be an exception thrown from ~A. So, naturally, throw in foo has to be called first and then during the second throw everything breaks.
If I'm not mistaken, once terminate is called, no (further) stack unwinding would occur.
terminate calls a handler function (which you can set with set_terminate):
The type of a handler function to be
called by terminate() when terminating
exception processing.
Required
behavior:
A terminate_handler shall terminate execution of the program
without returning to the caller.
Default behavior:
The implementation's default terminate_handler calls abort().
At least I don't know of a way to "terminate execution without returning to the caller" that would allow you to unwind the stack.
You can modify the example to see what you can expect:
#include <cstdio>
class A
{
public:
~A() {
puts("Entered A destructor");
throw "error";
}
};
void foo()
{
A a, b;
throw "error";
}
int main()
{
try {
foo();
} catch (const char*) {
return 1;
}
}
Now there are two A instances, and the destructor of the second one is never called, because the execution was terminated as soon as the destructor of the first A finished and let another exception escape.
Object a is a stack object, so there is no dynamic memory to be freed. Once control goes out of the scope of foo(), the stack frame, and therefore the object, no longer exists.
To illustrate, here's what happens in Microsoft C++:
#include <iostream>
class A {
public:
~A() {
std::cout << "in ~A" << std::endl;
throw "error";
}
};
void foo() {
A a;
std::cout << "in foo" << std::endl;
throw "error";
}
int main() {
try {
foo();
}
catch (void *) {
std::cout << "exit: 1" << std::endl;
return 1;
}
std::cout << "exit: 0" << std::endl;
return 0;
}
And the result:
>cpptest1.exe
in foo
in ~A
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
>