[comp.lang.c++] How do I call destructors on ^C in TC++?

scholes@spot.Colorado.EDU (Genuine Bud Man) (05/24/91)

  Please excuse me if this is a FAQ, or if I am missing something
painfully obvious, but destructors don't seem to be called when
the user hits ^C in Turbo C++.
  I developed a class library for giving "sort of" virtual data
space.  The program requests X amount of mem, and the class tries
to satisfy the request first thru main memory, XMS, then disk space.
I have alloc, read, write, and free functions.  Each class instance
may only be manipulating one block of memory at a time, so multiple
class instances are running (at least in my stat app).  The problem
is that when the user types ^C, the destructors are not called, and
if the memory is in XMS or disk, then the XMS is not freed, or the
swap file not deleted.
  I could easily write a ^C handler, and intercept ^C, but how
would the handler know who to call, since the class instances are
auto vars of another function?  I could have the handler ignore ^C,
but I would like to have that functionality.
  I am new to C++, so there may be something staring me in the
face here, but I am lost as to what to do.  I guess the same basic
problem would exist in C, so how would it be handled?  Global
variables?                          Thanx in advance, Marty

ahodgson@athena.mit.edu (Antony Hodgson) (05/24/91)

In article <1991May24.045847.24401@colorado.edu> scholes@spot.Colorado.EDU (Genuine Bud Man) writes:
>  Please excuse me if this is a FAQ, or if I am missing something
>painfully obvious, but destructors don't seem to be called when
>the user hits ^C in Turbo C++.
.. stuff deleted
>The problem is that when the user types ^C, the destructors are not called,
>and if the memory is in XMS or disk, then the XMS is not freed, or the
>swap file not deleted.
>  I could easily write a ^C handler, and intercept ^C, but how
>would the handler know who to call, since the class instances are
>auto vars of another function?

If ^C does the equivalent of exit(), then only global variable destructors
are called.  If it does the equivalent of abort(), no destructors are ever
called.  Borland C++ does have the atexit pragma, but since you can't
pass parameters to it, you must have global variables available to tell
you what swap files exist or what XMS blocks are not yet freed.

Tony Hodgson
ahodgson@hstbme.mit.edu

steve@taumet.com (Stephen Clamage) (05/25/91)

scholes@spot.Colorado.EDU (Genuine Bud Man) writes:


>  Please excuse me if this is a FAQ, or if I am missing something
>painfully obvious, but destructors don't seem to be called when
>the user hits ^C in Turbo C++.

Until exceptions are part of the language, this is the problem of
interrupted control flow.

If you have a local object and suddenly jump out of the function where it
was constructed (as from an interrupt or longjmp) the destructor will not
be called, and there is no way to ensure that it will be called.

Destructors for static objects will be called if you exit the program
normally, by returning from main() or by calling exit().  If you call
abort(), these destructors will not be called.

If you want a graceful exit from a program which may be interrupted:

1.  Avoid local objects which have destructors with important side
    effects.  You have to assume that the destructors might not be called
    unless you disable interrupts during the lifetime of those objects.

2.  Catch the keyboard interrupt and do whatever cleanup is needed;
    then call exit().

An unimportant side effect is freeing storage.  An important side effect
might be flushing an output buffer or restoring terminal attributes.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

Antony.Hodgson@sunbrk.FidoNet.Org (Antony Hodgson) (05/25/91)

In article <1991May24.045847.24401@colorado.edu> scholes@spot.Colorado.EDU (Genuine Bud Man) writes:
>  Please excuse me if this is a FAQ, or if I am missing something
>painfully obvious, but destructors don't seem to be called when
>the user hits ^C in Turbo C++.
.. stuff deleted
>The problem is that when the user types ^C, the destructors are not called,
>and if the memory is in XMS or disk, then the XMS is not freed, or the
>swap file not deleted.
>  I could easily write a ^C handler, and intercept ^C, but how
>would the handler know who to call, since the class instances are
>auto vars of another function?

If ^C does the equivalent of exit(), then only global variable destructors
are called.  If it does the equivalent of abort(), no destructors are ever
called.  Borland C++ does have the atexit pragma, but since you can't
pass parameters to it, you must have global variables available to tell
you what swap files exist or what XMS blocks are not yet freed.

Tony Hodgson
ahodgson@hstbme.mit.edu

 * Origin: Seaeast - Fidonet<->Usenet Gateway - sunbrk (1:343/15.0)

s892992@minyos.xx.rmit.oz.au (Kendall Bennett) (05/27/91)

scholes@spot.Colorado.EDU (Genuine Bud Man) writes:

>  Please excuse me if this is a FAQ, or if I am missing something
>painfully obvious, but destructors don't seem to be called when
>the user hits ^C in Turbo C++.

>  I could easily write a ^C handler, and intercept ^C, but how
>would the handler know who to call, since the class instances are
>auto vars of another function?  I could have the handler ignore ^C,
>but I would like to have that functionality.

   I am pretty sure that if you call the exit() standard library function it
calls the destructors for any AUTO variables, that is any instances that have
been allocated on the stack. If the class instance was allocted in the heap,
then it is up to the program to delete it - so I don't know how you would
handle this one.

See ya,
       Kendall Bennett (s892992@minyos.xx.rmit.oz.au)

steve@taumet.com (Stephen Clamage) (05/27/91)

s892992@minyos.xx.rmit.oz.au (Kendall Bennett) writes:

|   I am pretty sure that if you call the exit() standard library function it
|calls the destructors for any AUTO variables, that is any instances that have
|been allocated on the stack. If the class instance was allocted in the heap,
|then it is up to the program to delete it - so I don't know how you would
|handle this one.

No, exit() will not call destructors for auto objects, since the language
definition does not require that sort of bookkeeping.  Destructors only
for static objects only will be called when a program terminates via exit().
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

Stephen.Clamage@sunbrk.FidoNet.Org (Stephen Clamage) (05/28/91)

s892992@minyos.xx.rmit.oz.au (Kendall Bennett) writes:

|   I am pretty sure that if you call the exit() standard library function it
|calls the destructors for any AUTO variables, that is any instances that have
|been allocated on the stack. If the class instance was allocted in the heap,
|then it is up to the program to delete it - so I don't know how you would
|handle this one.

No, exit() will not call destructors for auto objects, since the language
definition does not require that sort of bookkeeping.  Destructors only
for static objects only will be called when a program terminates via exit().
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

 * Origin: Seaeast - Fidonet<->Usenet Gateway - sunbrk (1:343/15.0)

horstman@mathcs.sjsu.edu (Cay Horstmann) (05/29/91)

In article <1991May27.024810.2300@minyos.xx.rmit.oz.au> s892992@minyos.xx.rmit.oz.au (Kendall Bennett) writes:
>scholes@spot.Colorado.EDU (Genuine Bud Man) writes:
>
>>  Please excuse me if this is a FAQ, or if I am missing something
>>painfully obvious, but destructors don't seem to be called when
>>the user hits ^C in Turbo C++.
>
>   I am pretty sure that if you call the exit() standard library function it
>calls the destructors for any AUTO variables, that is any instances that have
>been allocated on the stack. If the class instance was allocted in the heap,
>then it is up to the program to delete it - so I don't know how you would
>handle this one.
>
Fat chance. No such thing will happen. When you call exit(), the stack
just gets popped, the free store given back wholesale. I am not sure whether
STATIC destructors are run. Someone here surely knows the answer. 

Cay

jbuck@forney.berkeley.edu (Joe Buck) (05/29/91)

In article <1991May28.225141.1451@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes:
|> In article <1991May27.024810.2300@minyos.xx.rmit.oz.au> s892992@minyos.xx.rmit.oz.au (Kendall Bennett) writes:
|> >   I am pretty sure that if you call the exit() standard library function it
|> >calls the destructors for any AUTO variables, that is any instances that have
|> >been allocated on the stack. If the class instance was allocted in the heap,
|> >then it is up to the program to delete it - so I don't know how you would
|> >handle this one.
|> >
|> Fat chance. No such thing will happen. When you call exit(), the stack
|> just gets popped, the free store given back wholesale. I am not sure whether
|> STATIC destructors are run. Someone here surely knows the answer. 

Cay's right; there's no provision in Turbo C++ or or cfront up through 2.1
that would allow you to have a control-C interrupt call destructors for
the auto variables.

When exceptions become commonly available, there will be a solution: the
control-C signal handler can throw an exception, and if you want to catch
it at the top level and exit, you can write your main() something like

#include <signal.h>

class IntSignal {
	// stuff goes here
};

void intCatcher() throw IntSignal {
	throw IntSignal();
}

int main (int argc, char ** argv) {
	// I'm being sloppy, should check the current status
	// of signal handling.
	signal (SIGINT, intCatcher);
	try {
		// body of main goes here
	}
	catch (IntSignal& isig) {
		cerr << "Caught a SIGINT, exiting\n";
		exit(1);
	}
}

The exception handling mechanism will cause all auto values on the
stack to have their destructors called.
--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck