When an object is created in your main() function, is its destructor called upon program termination? I would assume so since main() still has a scope( the entire program ), but I just wanted to make sure.
It depends on how your program terminates. If it terminates by having main return (either by an explicit return or falling off the end), then yes, any automatic objects in main will be destructed.
But if your program terminates by calling exit(), then main doesn't actually go out of scope and any automatic objects will not be destructed.
The scope of declarations inside main() is not the entire program. It behaves just like any normal function. So, yes, destructors of local class objects execute as expected. Unless the program terminates abnormally.
Related
Suppose I am doing something like:
try
{
do_job();
}
catch(...)
{
std::cout << "GUI is running so we won't terminate and raise a clear error here instead" << std::endl;
};
When calling a failing do_job some static variables/classes are initiated, are they "destroyed" after the catch? If not how to handle this please (i.e. memory allocated to statics)?
My generic problem is: I am having a GUI looping to display stuff to the user, say a game, if an error occur, the program will call std::termniate() I guess, or something similar, but I will find myself in the lovely file <abort>, the GUI then is crached, how can I handle this and reset static variables created when do_job is called please? Shoud I just let them initiated? The user in this case might change mind and not even use the static variables that have been created, so they are there with no use taking memory?
Static storage duration variables, if they have been successfully initialized, will always be destroyed at normal program termination, not earlier.
If a static variable wasn't successfully initialized then it will not be destroyed.
In any case there is nothing for you to take care of under normal conditions. In particular when throwing from do_job, either the static has been fully initialized at the point of the throw or it hasn't been. In the former case it will be destroyed at normal program termination, in the latter case it doesn't need to be destroyed.
In the situation of a std::terminate call, it looks different. It is called under abnormal conditions, such as if an exception is uncaught or an exception thrown while stack unwinding is in progress or an exception escapes a noexcept function.
The default std::terminate handler will call std::abort which abnormally terminates the program and explicitly does not destruct any static storage duration objects. The program just abruptly terminates without any chance to execute any further instructions (except maybe for a SIGABRT handler).
The std::terminate handler can be replaced, but the conditions under which std::terminate is called don't really allow for normal program termination and surely not for sensible continuation of program execution.
The best solution is to not let the abnormal conditions causing it to be called happen. Make sure to not let exceptions escape from main, destructors or noexcept functions. (There are more sources of std::terminate calls. All of them should be avoided.)
When calling a failing do_job some static variables/classes are initiated, are they "destroyed" after the catch?
Variables with static storage duration are destroyed after main returns (either normally, or call to std::exit).
In a multithread C++ program, is it possible to use std::exit correctly in the middle of a parallel execution, with other running threads?
In other words, what are the preconditions to use std::exit?
Are third party libraries generally safe for such use?
Note: calling std::exit is the same as returning from an empty block in main:
int main(.....)
{ // nothing here
{
all the real code......
}
return 0;
}
Remark: the focus here is on the other threads; obviously returning from all functions called from main to be able to return means that all the local variables are properly destructed. That's was always true, even in pre standard C++. That isn't the point here as it isn't a thread issue.
Your premis is false. You dont need threads to break stuff with std::exit. From cppreference:
Stack is not unwound: destructors of variables with automatic storage duration are not called.
Hence, for example this will not do the right thing:
int main() {
auto x = some_raii_type_that_writes_to_file_on_destruction("file.ext");
std::exit();
}
When you normally return from main, then...
Returning from the main function, either by a return statement or by reaching the end of the function performs the normal function termination (calls the destructors of the variables with automatic storage durations) and then executes std::exit, passing the argument of the return statement (or 0 if implicit return was used) as exit_code.
That being said, std::exit will only perform the following steps (again cppreference:
1) The destructors of objects with thread local storage duration that are associated with the current thread, the destructors of objects with static storage duration, and the functions registered with std::atexit are executed concurrently, [...]
2) all C streams are flushed and closed
3) files created by std::tmpfile are removed
4) control is returned to the host environment. [...]
Considering that the stack is not unwound (neither of the thread that calls std::exit nor others), you cannot expect some third party library to behave in a "safe" way.
I'm interfacing a C program (main() is in C) with C++. At some points in my code I want to stop execution of the program. Now I'd like to know, how can I do this cleanly?
At the moment I call std::terminate() but more out of a lack of better ideas. The main thing that bugs me isn't even that I'm not freeing the memory (because it's freed anyway on program termination, right?) but that the MSVS Just-in-time Debugger pops up and I get an ugly error message about terminating the runtime in an unusual way.
EDIT: As this has caused confusion: Returning from main() with return 0 is not possible in this case.
If you concern about cleaning up and invoking destuctors then
exit(EXIT_SUCCESS); // or EXIT_FAILURE
is the best choice between exit, terminate and abort.
Function exit calls descructors and cleans up the automatic storage objects (The object which declared in the global scope). It also calls the functions passed to atexit.
Function abort is useful for abnormal exits and will not clean up anything. It doesn't call the functions passed to atexit.
Function terminate does not exist in C. It's useful when you have an exception and you can't handle it but finishing the program.
main function is where it starts, main function is where it should end usually. If you use return 0; it indicates succesful exit.
int main(void) {
//init
//do stuff
//deinit
return 0; // bye bye
}
You could also use exit(0);, but if your exit points are scattered all over the place it makes things harder to debug.
Assuming that init is the last global object being initialized before main() (and we don't need any command line argument), can I do something like:
struct int_main {
int_main ()
{
//... start code execution
}
}init;
int main ()
{
}
Asking the question in this way, because I am interested in knowing if main() assures anything other than:
argc, argv from command line
All global objects are initialized
before it
You do not have a guarantee that all global objects are constructed before your object, so you may not use any of them. That includes vital parts of iostreams.
I normally use the pattern that main() just constructs the application object and invokes a method on it to perform the actual work.
You would have a hard time catching any exception from the int_main constructor.
Also you would have a hard time returning a process exit code with complete unwinding of the stack.
That's mainly what main provides in C++: a place to catch exceptions, and a means to return normally (not just exit) with a specified process exit code.
Cheers & hth.,
Within C\C++ you can declare the entry point of your application via the visual studio IDE. It's the convention that the entry point into you're code will be either be Main or in the case of a win32 exe WinMain.
As to answer your question, the CRT will iniailize all global variables in the order of
C Primitive Types
C Struct Types and or C++ Class types
Call the class constructors
Call the Entry point into your application, this will be done from CRTStartup (correct me if i'm wrong)
In theory this is possible, but you're not assured of the initialization order of global objects, so you are not going to have an assurance of which object will be initialized last, and therefore you're going to have a problem with running a "main" inside a global object that may not have the proper state of the program setup before its constructor is called. Furthermore, you're not going to be capable of suspending the execution of your "main" object's constructor to wait for the proper starting state to exist if such a scenario occurs.
Additionally, since the OS's runtime will be calling your actual main() function in order to actually "run" your program regardless of the presence of a "main" global object or not, you're going to need to return a value from 'main()` in order for the OS runtime to determine the exit status of your program.
I want to immediately exit my MFC app in C++. Is exit(0) the best solution? eg. does it prevent destructors from being called, is it threadsafe? etc. Is there a better solution? Thanks.
Yes, exit(0) is the best solution. It will cause the destructors of global objects (and static objects within functions) to run, however it will not cause destructors of stack-allocated or heap-allocated objects to run:
// At global scope
ClassWithDestruct globalObject;
void SomeFunction()
{
static ClassWithDestructor staticObject;
ClassWithDestructor stackObject;
ClassWithDestructor *heapObject = new ClassWithDestructor;
// On the following call to exit(), the destructors of 'globalObject' and
// 'staticObject' will run, but those of 'stackObject' and 'heapObject' will
// NOT run
exit(0);
}
As to whether or not it's thread-safe, that's a hard question to answer: you should not be calling exit simultaneously from multiple threads, you should only call it once. If any destructors run as a result of exit, or any if any functions registered with atexit run, then obviously those functions should be thread-safe if they deal with data that could potentially be being used by other threads.
If your program is exiting normally (say, as a result of the user requesting an exit), you should either call exit or return from main/WinMain, which is equivalent to calling exit. If your program is exiting abnormally (say, as a result of an access violation or failed assertion), you should call either _exit or abort, which do not call any destructors.
If you want to exit immediately, ensuring against running any destructors and such beforehand, then you probably want to call abort(). If you do want destructors to execute, then you probably want to use PostQuitMessage(0);. Either way, exit() is probably the wrong choice.
when a win32 process exits any resource associated with it is cleaned up by the OS, so in order to me it is perfectly ok.
exit(0) exits the process. All memory is cleaned up. On the other hand explicitly managed resources may not be closed. Of course file handles would be closed and stuff in windows buffers will be flushed. However stuff that the application manages will not.
No, it's not a safe way to end your program. Static-storage data and non-local automatic objects will destruct, but local automatic objects will not.
From 18.3/8 in the C++ standard:
The function exit() has additional
behavior in this International
Standard:
First, objects with static storage
duration are destroyed and functions
registered by calling atexit are
called. Non-local objects with static
storage duration are destroyed […].
(Automatic objects are not destroyed
as a result of calling
exit().)[207]) […] A local static
object obj3 is destroyed at the same
time it would be if a function calling
the obj3 destructor were registered
with atexit at the completion of the
obj3 constructor.
Next, all open C streams (as
mediated by the function signatures
declared in <cstdio>) with unwritten
buffered data are flushed, all open C
streams are closed, and all files
created by calling tmpfile() are
removed.[209])
[207]: Objects with automatic storage
duration are all destroyed in a
program whose function main()
contains no automatic objects and
executes the call to exit(). Control
can be transferred directly to such a
main() by throwing an exception that
is caught in main().
[209]: Any C streams associated with
cin, cout, etc (27.3) are flushed
and closed when static objects are
destroyed in the previous phase. The
function tmpfile() is declared in
<cstdio>.
On a related note, std::exit(EXIT_SUCCESS) is disturbingly misleading.