Simple question about exit(1)

V

Vicent Giner-Bosch

Hello.

If I do "exit(1)" in any part of my program, does it take into account
allocated space (instances of objects, and so on) and de-allocate it
before termining the execution??

To be more concrete:

The program defines an ofstream object (for text output), and a new
object via "new" statement, and then, in the middle of the execution,
it is possible that an "exit(1)" command arrises, so in that case the
lines where I "close" the ofstream object and I delete the object
created with the "new" statement will not be read. Is that fine??

Actually, this is all about handling exceptions, so, any hint, tip,
suggested reading...?

Thank you in advance for your answers!
 
M

mingze zhang

Hello.

If I do "exit(1)" in any part of my program, does it take into account
allocated space (instances of objects, and so on) and de-allocate it
before termining the execution??

To be more concrete:

The program defines an ofstream object (for text output), and a new
object via "new" statement, and then, in the middle of the execution,
it is possible that an "exit(1)" command arrises, so in that case the
lines where I "close" the ofstream object and I delete the object
created with the "new" statement will not be read. Is that fine??

Actually, this is all about handling exceptions, so, any hint, tip,
suggested reading...?

Thank you in advance for your answers!

you don't need to worry anything.

void exit ( int status );
Terminate calling process

Terminates the process normally, performing the regular cleanup for
terminating processes.

First, all functions registered by calls to atexit are executed in the
reverse order of their registration. Then, all streams are closed and
the temporary files deleted, and finally the control is returned to
the host environment.

The status argument is returned to the host environment.
 
F

Fred Zwarts

Vicent Giner-Bosch said:
Hello.

If I do "exit(1)" in any part of my program, does it take into account
allocated space (instances of objects, and so on) and de-allocate it
before termining the execution??

To be more concrete:

The program defines an ofstream object (for text output), and a new
object via "new" statement, and then, in the middle of the execution,
it is possible that an "exit(1)" command arrises, so in that case the
lines where I "close" the ofstream object and I delete the object
created with the "new" statement will not be read. Is that fine??

Actually, this is all about handling exceptions, so, any hint, tip,
suggested reading...?

If your only concern is deallocation of memory,
then it depends on your operating system environment.
Most operating systems will deallocate all memory at program exit.

However, exit is not handled as an exception.
So, no stack unwinding takes place.
It is possible that this leaves e.g. files, or databases in an inconsitent state,
if there are objects on the stack which require proper destruction.
Static objects, however, are destructed when exit is called.
This may cause strange behaviour if these destructors rely
on the stack objects being destructed already.
 
G

Goran

Hello.

If I do "exit(1)" in any part of my program, does it take into account
allocated space (instances of objects, and so on) and de-allocate it
before termining the execution??

Why do you want to exit like that? It's not needed and, to the
contrary of what some people said here, it's not very safe either.

On a full-fledged OS of today, like Windows/Unix, sure, all OS
resources will be freed, but what about e.g. your program data? E.g.
what if you started writing something to some file of yours and
terminated in the middle? If file OK? Will you be able to recover if
it's cut in a bad place?

In other words, you don't do exit(1) as a matter of fact, not in C,
not in C++.

Luckily, in C++, you can easily get what you want, which, I guess, is
to leave all your processing when something really catastrophic
happen. Here's what you can do:

In catastrophy.hpp

extern void catastrophy(int exit_code);

In catastrophy_impl.hpp

struct catastrophy_exception
{
catastrophy_exception(int exit_code): _exit_code(exit_code)
{
}
const int _exit_code;
};

In catastrophy_impl.cpp

void catastrophy(int exit_code)
{
throw catastrophy_exception(exit_code);
}

In main.cpp:

#include "catastrophy_impl.hpp"

int main(...)
{
try
{
workworkwork();
return 0;
}
catch(catastrophy_exception whoops)
{
return whoops._exit_code;
}
}

The above is a near-equivalent to exit(), but has a major advantage:
stack unwind happens. So as long as your code cleans-up properly in
case of exceptions (and that's what you should have anyhow), it's much
better.

In any other file, include catastrophy.hpp and call catastrophy() if
you need it. Don't ever try to catch catastrophy_exception, and don't
ever catch(...) without a rethrow. In fact, don't ever write
catch(...). Given exception handling tools we have today in C++,
catch(...) {} is a bug, even if it has a throw in it.

Given that you are asking in light of exceptions... You probably need
to learn how to write exception-safe code. That goes for C++ as well
as for any language that uses exceptions. That's tough, but
rewarding :).

Note: in files where you don't include catastrophy_impl.hpp, you can't
catch catastrophy_exception, that just won't compile, obvoiusly. So
don't include it, include only catastrophy.hpp!

Goran.
 
J

Juha Nieminen

Vicent Giner-Bosch said:
If I do "exit(1)" in any part of my program, does it take into account
allocated space (instances of objects, and so on) and de-allocate it
before termining the execution??

I wonder if there is any operating system in existence which is newer
than 30 years and which doesn't clean up the memory used by a program
which exited abruptly. There might have been some experimental single-user
operating systems in the 60's which needed to be rebooted after each
program execution in order to reset the memory usage (this assuming that
you could even return to the OS at all from apps).

I don't think even MS-DOS 1.0 "leaked" any memory after a program
terminated and it returned to the command line.
The program defines an ofstream object (for text output), and a new
object via "new" statement, and then, in the middle of the execution,
it is possible that an "exit(1)" command arrises, so in that case the
lines where I "close" the ofstream object and I delete the object
created with the "new" statement will not be read. Is that fine??

No OS I know of would fail to properly free the file handles which were
requested by a process which then failed to explicitly release them. Such
an OS would be rather useless (because, after all, even bug-free programs
can sometimes be terminated abruptly by external means).

The problems happen if your program itself needs to clean up. One typical
case is if it uses some temporary files which it should remove before it
terminates. Since these are just regular files, the OS won't do anything to
them. They are just files which the program created. If they should be
removed, the program has to do it. Naturally if you do a exit(1), those
files will not be removed because the program will be terminated right
there and no destructors will be called. (You could hook a cleaning
function with the atexit() standard function, but in C++ there usually
are better ways to do this.)
 
J

James Kanze

In Windows one can use the FILE_FLAG_DELETE_ON_CLOSE flag for
CreateFile() to have the file deleted on program exit. In
Linux/Unix one can achieve the same effect by opening a file,
then immediately unlink()-ing all references to it from the
disk directories. However, when one talks about "temporary
files" one probably means something else.

But these solutions don't work for standard streams, or at
least, the one for Windows doesn't (because the filebuf never
uses this flag when it does CreateFile).

Practically, too, it's not rare to want to close a temporary
file, then reopen it later.

It's possible to make this work, more or less, by registering
the temporary files with an object with static lifetime, which
deletes them in its destructor. In the case of Windows, you
still have to ensure that the file is closed first. Which
brings us to the one big problem with exit---it doesn't call the
destructors of local objects. So if you write something like:

void f()
{
std::string tmpname(getTempFileName());
std::fstream tmp(name.c_str());
TempFileManager::instance().register(tmpname);
// ...
if (something)
exit(1);
// ...
}

, the temp file will not get deleted.

One convention that I've used at times is that main() is always:

main(...)
{
try {
// actual code...
return errorStatus;
} catch ( int returnCode ) {
return returnCode;
}
}

Then, instead of calling exit(EXIT_FAILURE), you "throw
EXIT_FAILURE".
 
J

Jorgen Grahn

I wonder if there is any operating system in existence which is newer
than 30 years and which doesn't clean up the memory used by a program
which exited abruptly. There might have been some experimental single-user
operating systems in the 60's which needed to be rebooted after each
program execution in order to reset the memory usage (this assuming that
you could even return to the OS at all from apps).

I don't think even MS-DOS 1.0 "leaked" any memory after a program
terminated and it returned to the command line.

You don't have to go back to primitive things like DOS. AmigaDOS
(1985--1995--?) was a rather Unix-like multitasking OS, but did not
keep track of which process allocated memory or opened files.

The standard C library (shipped by your compiler vendor, not with the OS)
*did* have tracking of malloc()ed memory and open FILE* streams, but
(a) I'm not sure what loopholes there were in those schemes and (b)
many or most people rejected the standard library due to percieved
overhead.

I suspect contemporary OSes for embedded devices do it like that too,
but I only have some experience with VxWorks and OSE, and in both cases
I've used processes/tasks defined to always be running and never to be
terminated or restarted ...

....
No OS I know of would fail to properly free the file handles which were
requested by a process which then failed to explicitly release them. Such
an OS would be rather useless (because, after all, even bug-free programs
can sometimes be terminated abruptly by external means).

The AmigaDOS solution was simply not to have external abrupt
terminations, in the style of Ctrl-C or kill -9. That was the worst
effect of not having resource tracking, IMO. Other than that, I
thought at the time that it worked really well.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top