Topic: problems with C++ compatibility with C


Author: pardoej@lonnds.ml.com (Julian Pardoe LADS LDN X1428)
Date: 1995/07/06
Raw View
In article <1995Jun28.122439.12607@malibu.dst.battelle.org>, fleming@malibu.dst.battelle.org (Matt D. Fleming) writes:
-->throw and catch always seemed like cheap ways aroud writing a good program.
-->What I mean is, anything you can do with, can be done better (from a
-->standpoint of aesthetics, readability, etc.) without.

Hmm!  I haven't had enough experience with exceptions in practice and
I can believe that they can cause problems, but I'm also pretty
sure that sensible use can produce clearer, more readable code.

I once worked on a system that was almost entirely built up of routines
built on the pattern:

    int OpN (blah blah blah)
        {
        int result;

        result = Op1 (foo);
        if (result != OK)
            return result;

        result = Op2 (bar);
        if (result != OK)
            return result;

        ....
        return OK;
        }

The code would have been much simpler and much more readable if
error conditions had been communicated by exceptions.

It strikes me as a fairly good basic principle that the structure
of one's code should reflect the structure of the normal-case
algorithm.  Often error-handling code mucks this structure up
and/or obscures it.

Exceptions allow more information about what went wrong to be
passed back than other techniques do.

-- jP --






Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/07/02
Raw View
"Ronald F. Guilmette" <rfg@rahul.net> writes:

>Anyway, to respond further to your point, note that (as is often the
>case in C++) catch clauses are _never_ actually needed for _anything_.

That is basically wrong.  The only sense in which it is true is a
rather uninteresting one - Turing equivalence.

>You can always achieve the same effects by placing the code you want
>to have executed (upon exit from a given block) in the destructor for
>some object (i.e. any object) which is allocated from the stack frame
>for that block.

What if you want to do differebt things depending on whether you exit via
an exception or normally (e.g. via a return statement)?
What if you want to access the exception object thrown?
Etc.

--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh
"The unexamined life is not worth living" - Socrates.





Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/28
Raw View
Ronald F. Guilmette (rfg@rahul.net) wrote:
: In article <JASON.95Jun24145431@phydeaux.cygnus.com>,
: Jason Merrill <jason@cygnus.com> wrote:
: >>>>>> Ronald F Guilmette <rfg@rahul.net> writes:
: >
: >> Anyway, to respond further to your point, note that (as is often the
: >> case in C++) catch clauses are _never_ actually needed for _anything_.
: >> You can always achieve the same effects by placing the code you want
: >> to have executed (upon exit from a given block) in the destructor for
: >> some object (i.e. any object) which is allocated from the stack frame
: >> for that block.
: >
: >This is certainly true for cleanup code, but if you want to be able to
: >*recover* from an exception, you need a catch clause somewhere.

: OK.  I'll bite.  Why?

: ``Cleanup'' code could be stuck into the destructor for a local `auto'
: object.

Otherwise your progam will exit after executing terminate().

Which isn't "recovery".
--
        Tony Cook - tony@online.tmx.com.au
                    100237.3425@compuserve.com





Author: fleming@malibu.dst.battelle.org (Matt D. Fleming)
Date: 1995/06/28
Raw View
In article <JASON.95Jun27043905@phydeaux.cygnus.com> jason@cygnus.com (Jason Merrill) writes:
>>>>>> Ronald F Guilmette <rfg@rahul.net> writes:
>
>> In article <JASON.95Jun24145431@phydeaux.cygnus.com>,
>> Jason Merrill <jason@cygnus.com> wrote:
>>>>>>>> Ronald F Guilmette <rfg@rahul.net> writes:
>>>
>>>> Anyway, to respond further to your point, note that (as is often the
>>>> case in C++) catch clauses are _never_ actually needed for _anything_.
>>>> You can always achieve the same effects by placing the code you want
>>>> to have executed (upon exit from a given block) in the destructor for
>>>> some object (i.e. any object) which is allocated from the stack frame
>>>> for that block.
>>>
>>> This is certainly true for cleanup code, but if you want to be able to
>>> *recover* from an exception, you need a catch clause somewhere.
>
>> OK.  I'll bite.  Why?
>
>> ``Cleanup'' code could be stuck into the destructor for a local `auto'
>> object.
>
>Yes, it can.  That's why I agreed with you for the case of cleanup code.
>However, this sort of thing cannot be stuck into a destructor:  Without a
>catch clause, this program would terminate due to a recoverable failure.
>
>#include <iostream>
>
>main ()
>{
>  char *massive_cache = 0;
>  try {
>    massive_cache = new char[1048576];
>  } catch (bad_alloc) {
>    cerr << "Unable to allocate massive cache, continuing without..." << endl;
>  }
>  ...
>}

The same effect could be acheived without catch.  As in:

main(){
  char* massive_cache = 0;
  massive_cache = new char[1048576];
  if (massive_cache == 0){
    cerr << "Unable to allocate massive cache, continuing without..." << endl;
  }
  ...
}

throw and catch always seemed like cheap ways aroud writing a good program.
What I mean is, anything you can do with, can be done better (from a
standpoint of aesthetics, readability, etc.) without.

Cheers,
Matt

--
---------------------------------------------------------------------------
fleming.70@osu.edu         http://www.cis.ohio-state.edu/~fleming/home.html
fleming@cis.ohio-state.edu
fleming@malibu.dst.battelle.org    + Math/CIS major, hacker, Macintosh fan.





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/06/26
Raw View
Andreas Rossberg (rossberg@ips.cs.tu-bs.de) wrote:
|> Ronald F. Guilmette (rfg@rahul.net) wrote:
|> :
|> : Implementations could provide some help in implementing the Exit_Now class,
|> : and the exit_now exception.  Specifically, in order to make sure that
|> : programmers don't mistakenly try to catch any exception having the
|> : Exit_Now type (or any type derived therefrom) implementations could flag
|> : compile-time errors on attempts to define handlers for any such exception.


|> Why forbid catching exit exceptions? Besides such behaviour being
|> inconsistent with the exception scheme, catching such exceptions may
|> appear to be as useful as catching any unknown exception via catch(...):
|> to do some important cleanup and rethrow it. And maybe special treatment
|> is necessary on exits... just catch your Exit_Now - no more need for the
|> atexit function (well, at least it would be less common).

Because the (C) function calling exit presumably doesn't expect to get
called again, and may have left static state in an inconsistent state.
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung





Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/26
Raw View
James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
: In article <DAFynF.IGJ@online.tmx.com.au> tony@online.tmx.com.au (Tony
: Cook) writes:

: |> James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
: |> : In article <3rq8iv$543@usenet.interramp.com> Ofer LaOr
: |> : <us007953@pop3.interramp.com> writes:

: |> :     [Concerning the fact that a program may terminate without all of
: |> : the destructors being called...]
: |> : |> That could cause system resources to dwindle, or system crash!

: |> : That sounds like a serious error in the system.  What kind of a system
: |> : maintains resources allocated to a process which has terminated?

: |> Any system with a file system?

: A normal file (and a directory, a socket, a named pipe, etc.) are not
: resources which belong to the process, and so should not be deleted.
: Any locks and/or exclusive accesses, on the other hand, do belong to
: the process, and should be released when the process terminates.  (Off
: hand, I know of no OS which directly supports file/record locking and
: doesn't do this.)  Or are you suggesting that a good system should
: systematically delete any files created by a process when the process
: terminates:-)?

The discussion above was in reference to destructors not being
called.

: A temporary file *will* be deleted by the system when the process
: terminates.  A system which does *not* do this cannot have a
: conforming C implementation.  See tmpfile, in the C/C++ standard.

tmpfile temporary files are not useful in some instances - for
example an I/O library that only works with files with names, a fax
library that requires images in some special format.

--
        Tony Cook - tony@online.tmx.com.au
                    100237.3425@compuserve.com





Author: "Ronald F. Guilmette" <rfg@rahul.net>
Date: 1995/06/27
Raw View
In article <JASON.95Jun24145431@phydeaux.cygnus.com>,
Jason Merrill <jason@cygnus.com> wrote:
>>>>>> Ronald F Guilmette <rfg@rahul.net> writes:
>
>> Anyway, to respond further to your point, note that (as is often the
>> case in C++) catch clauses are _never_ actually needed for _anything_.
>> You can always achieve the same effects by placing the code you want
>> to have executed (upon exit from a given block) in the destructor for
>> some object (i.e. any object) which is allocated from the stack frame
>> for that block.
>
>This is certainly true for cleanup code, but if you want to be able to
>*recover* from an exception, you need a catch clause somewhere.
>
>Jason

OK.  I'll bite.  Why?

``Cleanup'' code could be stuck into the destructor for a local `auto'
object.
--

-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- E-mail: rfg@segfault.us.com ----------- Purveyors of Compiler Test ----
---- finger: rfg@rahul.net ----------------- Suites and Bullet-Proof Shoes -





Author: jason@cygnus.com (Jason Merrill)
Date: 1995/06/27
Raw View
>>>>> Ronald F Guilmette <rfg@rahul.net> writes:

> In article <JASON.95Jun24145431@phydeaux.cygnus.com>,
> Jason Merrill <jason@cygnus.com> wrote:
>>>>>>> Ronald F Guilmette <rfg@rahul.net> writes:
>>
>>> Anyway, to respond further to your point, note that (as is often the
>>> case in C++) catch clauses are _never_ actually needed for _anything_.
>>> You can always achieve the same effects by placing the code you want
>>> to have executed (upon exit from a given block) in the destructor for
>>> some object (i.e. any object) which is allocated from the stack frame
>>> for that block.
>>
>> This is certainly true for cleanup code, but if you want to be able to
>> *recover* from an exception, you need a catch clause somewhere.

> OK.  I'll bite.  Why?

> ``Cleanup'' code could be stuck into the destructor for a local `auto'
> object.

Yes, it can.  That's why I agreed with you for the case of cleanup code.
However, this sort of thing cannot be stuck into a destructor:  Without a
catch clause, this program would terminate due to a recoverable failure.

Jason

#include <iostream>

main ()
{
  char *massive_cache = 0;
  try {
    massive_cache = new char[1048576];
  } catch (bad_alloc) {
    cerr << "Unable to allocate massive cache, continuing without..." << endl;
  }
  ...
}





Author: jason@cygnus.com (Jason Merrill)
Date: 1995/06/24
Raw View
>>>>> Ronald F Guilmette <rfg@rahul.net> writes:

> Anyway, to respond further to your point, note that (as is often the
> case in C++) catch clauses are _never_ actually needed for _anything_.
> You can always achieve the same effects by placing the code you want
> to have executed (upon exit from a given block) in the destructor for
> some object (i.e. any object) which is allocated from the stack frame
> for that block.

This is certainly true for cleanup code, but if you want to be able to
*recover* from an exception, you need a catch clause somewhere.

Jason





Author: "Ronald F. Guilmette" <rfg@rahul.net>
Date: 1995/06/24
Raw View
In article <DAGvox.JJn@ips.cs.tu-bs.de>,
Andreas Rossberg <rossberg@ips.cs.tu-bs.de> wrote:
>Ronald F. Guilmette (rfg@rahul.net) wrote:
>:
>: Implementations could provide some help in implementing the Exit_Now class,
>: and the exit_now exception.  Specifically, in order to make sure that
>: programmers don't mistakenly try to catch any exception having the
>: Exit_Now type (or any type derived therefrom) implementations could flag
>: compile-time errors on attempts to define handlers for any such exception.
>
>
>Why forbid catching exit exceptions? Besides such behaviour being
>inconsistent with the exception scheme, catching such exceptions may
>appear to be as useful as catching any unknown exception via catch(...):
>to do some important cleanup and rethrow it. And maybe special treatment
>is necessary on exits... just catch your Exit_Now - no more need for the
>atexit function (well, at least it would be less common).

My idea for a special ``Exit_Now'' kind of exception was put forward here
as a solution for the problem that (in C++ programs) we seem to lack any
facility or mechanism whereby code can ask that the entire program be
terminated quickly _but_ with a minimally reasonable set of cleanup
actions (i.e. destructor executions) occuring as the program exits.

Anyway, to respond further to your point, note that (as is often the
case in C++) catch clauses are _never_ actually needed for _anything_.
You can always achieve the same effects by placing the code you want
to have executed (upon exit from a given block) in the destructor for
some object (i.e. any object) which is allocated from the stack frame
for that block.
--

-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- E-mail: rfg@segfault.us.com ----------- Purveyors of Compiler Test ----
---- finger: rfg@rahul.net ----------------- Suites and Bullet-Proof Shoes -





Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/19
Raw View
In article <3rq8iv$543@usenet.interramp.com> Ofer LaOr
<us007953@pop3.interramp.com> writes:

    [Concerning the fact that a program may terminate without all of
the destructors being called...]
|> That could cause system resources to dwindle, or system crash!

That sounds like a serious error in the system.  What kind of a system
maintains resources allocated to a process which has terminated?

There will always be ways that a process terminates without calling
all of its destructors (segment violations, etc.).  It is up to the
system to handle this gracefully, and free all system resources.  (And
yes, I know that Unix is not very good in this regard.)
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/19
Raw View
James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
: In article <3rq8iv$543@usenet.interramp.com> Ofer LaOr
: <us007953@pop3.interramp.com> writes:

:     [Concerning the fact that a program may terminate without all of
: the destructors being called...]
: |> That could cause system resources to dwindle, or system crash!

: That sounds like a serious error in the system.  What kind of a system
: maintains resources allocated to a process which has terminated?

Any system with a file system?

--
        Tony Cook - tony@online.tmx.com.au
                    100237.3425@compuserve.com





Author: rossberg@ips.cs.tu-bs.de (Andreas Rossberg)
Date: 1995/06/20
Raw View
Ronald F. Guilmette (rfg@rahul.net) wrote:
:
: Implementations could provide some help in implementing the Exit_Now class,
: and the exit_now exception.  Specifically, in order to make sure that
: programmers don't mistakenly try to catch any exception having the
: Exit_Now type (or any type derived therefrom) implementations could flag
: compile-time errors on attempts to define handlers for any such exception.


Why forbid catching exit exceptions? Besides such behaviour being
inconsistent with the exception scheme, catching such exceptions may
appear to be as useful as catching any unknown exception via catch(...):
to do some important cleanup and rethrow it. And maybe special treatment
is necessary on exits... just catch your Exit_Now - no more need for the
atexit function (well, at least it would be less common).


 - Andreas Rossberg






Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/20
Raw View
In article <DAFynF.IGJ@online.tmx.com.au> tony@online.tmx.com.au (Tony
Cook) writes:

|> James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
|> : In article <3rq8iv$543@usenet.interramp.com> Ofer LaOr
|> : <us007953@pop3.interramp.com> writes:

|> :     [Concerning the fact that a program may terminate without all of
|> : the destructors being called...]
|> : |> That could cause system resources to dwindle, or system crash!

|> : That sounds like a serious error in the system.  What kind of a system
|> : maintains resources allocated to a process which has terminated?

|> Any system with a file system?

A normal file (and a directory, a socket, a named pipe, etc.) are not
resources which belong to the process, and so should not be deleted.
Any locks and/or exclusive accesses, on the other hand, do belong to
the process, and should be released when the process terminates.  (Off
hand, I know of no OS which directly supports file/record locking and
doesn't do this.)  Or are you suggesting that a good system should
systematically delete any files created by a process when the process
terminates:-)?

A temporary file *will* be deleted by the system when the process
terminates.  A system which does *not* do this cannot have a
conforming C implementation.  See tmpfile, in the C/C++ standard.

Come to think of it, this is one feature of stdio for which there is
no equivalent in iostream.  While it is easy to do on any given
system, there is no portable way of doing it.  (For example, Unix
requires the file to be `unlink'ed (deleted) as soon as it is created,
before it is used.  This tactic will not work in any other system I'm
aware of.  This will also result in the file being deleted when it is
closed, not at the end of process.  Since the file has no name,
however, I do not think that there is any way a conforming program can
detect this.)
--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung







Author: "Ronald F. Guilmette" <rfg@rahul.net>
Date: 1995/06/18
Raw View
In article <3rncdf$anr@usenet.interramp.com>,
Ofer LaOr  <us007953@pop3.interramp.com> wrote:
>I've posted a note to Bjarn about a year and a half ago about these
>issues, just wanna find out what's going on with them...
>
>First thing:
> running a C compatible exit() from somewhere inside C++ code (could be
> nested because C++ code uses a C library that calls exit to abort
> program) - causes automatic variables not to "close".
>
>I suggested having the standard define a c++ version of exit (that
> even libraries call when linking to your program)...

Overall, I'd say that this is a Good Idea.

If you want to exit immediately from an entire C++ program, and if you also
want the objects belonging to all active scopes to be properly destructed,
you can always just throw an exception which is not handled by any block.
Eventiually, this exception will propagate all of the way out of `main'.

Sadly, what happens then is probably undefined behavior or perhaps imple-
mentation-defined behavior.

It would definitely be Nice to have a special *reserved* exception... let's
call it the ``exit_now'' exception.  It might be a value of a specialized
(reserved) class.  Let's call it the Exit_Now class.

Implementations could provide some help in implementing the Exit_Now class,
and the exit_now exception.  Specifically, in order to make sure that
programmers don't mistakenly try to catch any exception having the
Exit_Now type (or any type derived therefrom) implementations could flag
compile-time errors on attempts to define handlers for any such exception.

Additionally, implementation could provide specialized ``friendly'' handling
of the propagation of Exit_Now exceptions out of `main'.  Specifically,
rather than producing a nasty-gram to stderr (which is what I hope and
expect most implementations to do when exceptions are propagated out of
`main') an implementation could recognize that it is a specailized Exit_Now
kind of exception which has propagated out of `main', and the implementation
could then simply extract the ``value'' of the exception (presumed to be
just a simple integer code) and then just quietly return it to the environ-
ment as the program's exit status.

I wish that this sort of facility/capability was mandated by the standard.
As the original poster noted, it would be very helpful to have this kind
of capability, especially when writing libraries.
--

-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- E-mail: rfg@segfault.us.com ----------- Purveyors of Compiler Test ----
---- finger: rfg@rahul.net ----------------- Suites and Bullet-Proof Shoes -





Author: Ofer LaOr <us007953@pop3.interramp.com>
Date: 1995/06/15
Raw View
That's fine- I don't have any problem with my own code throwing
exceptions, unfortunatly there is a LOT of code out there which is
C.

That is in itself not a problem, but since there is no standard
for C++ libraries for a lot of subjects, standard C library
is being used all over the place.

Since that is the case, The C standard library (which uses Assert,
Abort, exit) might cause perfectly valid C++ code to crap out.

That could cause system resources to dwindle, or system crash!

That doesn't sound too good, I think it should be included in the draft.

Ofer.






Author: Ofer LaOr <us007953@pop3.interramp.com>
Date: 1995/06/14
Raw View
I've posted a note to Bjarn about a year and a half ago about these
issues, just wanna find out what's going on with them...

First thing:
 running a C compatible exit() from somewhere inside C++ code (could be
 nested because C++ code uses a C library that calls exit to abort
 program) - causes automatic variables not to "close".

I suggested having the standard define a c++ version of exit (that
 even libraries call when linking to your program) and ammend the
 start up and end code of the application to do the following:

int asm_main(...)
{
  try { // compiler puts this up behind the scenes...
      return main ();
  }
  catch (exit_app exit) {
     return  exit.code();
  }
  catch (...) {
      return default_error_handler();
  }

}








Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/06/14
Raw View
In article anr@usenet.interramp.com, Ofer LaOr <us007953@pop3.interramp.com> writes:
>I've posted a note to Bjarn about a year and a half ago about these
>issues, just wanna find out what's going on with them...
>
>First thing:
> running a C compatible exit() from somewhere inside C++ code (could be
> nested because C++ code uses a C library that calls exit to abort
> program) - causes automatic variables not to "close".

Calling exit() does not cause auto variables to be destroyed. That is part
of the language definition. If you want to quit the program but still have
auto variables destroyed, throw an exception that is caught in main. Example:

 class exit_app { ... }; // an exception class

 main(int argc, char** argv)
 {
     try {
  ... ;
  return <something>;
     }
     catch( exit_app ) {
  return <something>;
     }
 }

>
>I suggested having the standard define a c++ version of exit (that
> even libraries call when linking to your program) and ammend the
> start up and end code of the application to do the following:
>
>int asm_main(...)
>{
>  try { // compiler puts this up behind the scenes...
>      return main ();
>  }
>  catch (exit_app exit) {
>     return  exit.code();
>  }
>  catch (...) {
>      return default_error_handler();
>  }
>
>}

It appears the problem you want to solve is that a C library function called
from a C++ program calls exit, leaving undestroyed auto variables. I never
saw any proposal to solve this problem if it was submitted to the C++
committee. The current draft standard contains nothing like what you
have suggested.

---
Steve Clamage, stephen.clamage@eng.sun.com