Topic: exceptions & pointers


Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/05/22
Raw View
Bernhard Brunner (brn@iis.fhg.de) wrote:
|> In article <KANZE.95May17105720@slsvhdt.lts.sel.alcatel.de>, kanze@lts.sel.alcatel.de
|> says...
|> >
|> >I don't understand what you are trying to say: "pointers outside of an
|> >object will be reduced to pure aliases.  Do you mean that the standard
|> >class does not support pointer arithmetic?  (I'm tempted to say that
|> >this would be a good thing.)
|> >

|> What I tried to say was, that in C it's perfectly legal to have an object (of
|> any possible type) referenced by a single pointer, no other references will
|> exist. Even more, this is the only way to hold a 'primary reference' to a
|> memory resource, although other references to this object may exist (aliases).

This remains true in C++, even in the presence of exceptions.

If you have only one pointer to the object, then auto_ptr is perfect.
(Auto_ptr becomes problematic when you have several pointers to a single
object; the auto_ptr must be the owner.)

|> |> ...[The language] provides exceptions and it provides an
|> |> operator new, which is mainly used to initialize pointers. Both are fine in
|> |> own right. But if you want them to work together you have to supply constructs
|> |> which are not part of the language. Ok, you can use components of the standard
|> |> libraries, but these are NOT part of the language. IMHO, this leaves the
|> |> conclusion, that the language is incomplete to some point.
|> >
|> >I think the problem is because C++ addresses programming at all
|> >levels.  At the lowest level, where you are actually manipulating
|> >pointers and using new directly, exceptions should probably be
|> >avoided.  Thus, for example, an implementation of string or vector
|> >should probably *not* call a lot of complex functions that may throw
|> >exceptions.  At the levels where most of us work, however, it is new
|> >and pointer manipulation that will not be present.
|> >

|> I agree with you in principle, but I get the feeling that low level
|> support has been degraded by all those fancy high level features.
|> So we soon may reach the point, where C++ cannot be used by low level
|> programmers anymore, which would be a pity.

I don't think there is any risk in this for the moment.  Obviously,
there *will* be restrictions on what you can do if you want to remain at
the lowest level.

|> >Even at the lowest level, I see very little use for new except when
|> >the pointer is maintained by a class (which allows for clean-up in the
|> >destructor).
|> >

|> Well, this depends very much on the programming style. I like those
|> Object* p = new Object(somewhat); stuff quite a lot, and I think I'm not the
|> only one :-).

So try:

 auto_ptr< Object > p = new Object( somewhat ) ;

It should work exactly the same.

I am curious, though.  Where do you use this idiom?

|> [...]
|> |> Now that's the point. Can we afford to throw away a huge amount of already
|> |> written software (using pointers the old way), because it will fail when
|> |> exceptions are introduced, or rather leave exceptions alone and stay with
|> |> the old libraries? If someone starts a project totally from scrap, fine.
|> |> But a lot of people may not have this choice, so they will not be able to use
|> |> exceptions for a long time (as I remember, it took more than a decade to get
|> |> some libraries ported from FORTRAN to C). Worse yet, in the future you may
|> |> not even be able to use new libraries, because they use exceptions. There may
|> |> be workarounds, of course, but this will involve a lot of work, which could have
|> |> been avoided.
|> >
|> >Well, exceptions were presented in the ARM, which is copyright 1990 or
|> >1991.  So we've already had 5 years to prepare.

|> Now be serious here. Exceptions were proposed then, but the first commercial
|> compilers that really supported them are not older than about 2 years.
|> (I think Watcom 9.5 was one of the first, and it worked awfully.)
|> I don't think, too many programmers had the foresight, to adopt to a
|> language feature, they could't even use.

Regretfully, you are probably right.  There are a lot of C++ programmers
who continue using C-style idioms for a lot of things.

|> >What worries me most isn't that the problems will be frequent, but
|> >that there is nothing that will signal them.  Programs with such
|> >problems will compile, and often pass most of the trivial tests, only
|> >to fail in the field.

|> As I stated above, this will be the real problem. And, given that exceptions
|> are a rather rare event, I wish good luck to everyone, who has to debug
|> these applications :-); even more, because undestroyed objects will most of the
|> time go undetected and cause no trouble, nevertheless they represent a bug.

|> What is really annoying me, is that this need not be so. It could have been
|> solved by introducing at least a 'poor man's garbage collection' at the same
|> time as exceptions. It had to run only after an exception was thrown.
|> I understand that this is is easier said than implemented, but it would have
|> reduced all the mentioned problems to void.

Agreed, 100%.  In the meantime, I expect that I will be pushing my
customers to use the Boehm collector.
--
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: brn@iis.fhg.de (Bernhard Brunner)
Date: 1995/05/19
Raw View
In article <KANZE.95May17105720@slsvhdt.lts.sel.alcatel.de>, kanze@lts.sel.alcatel.de
says...
>
>I don't understand what you are trying to say: "pointers outside of an
>object will be reduced to pure aliases.  Do you mean that the standard
>class does not support pointer arithmetic?  (I'm tempted to say that
>this would be a good thing.)
>

What I tried to say was, that in C it's perfectly legal to have an object (of
any possible type) referenced by a single pointer, no other references will
exist. Even more, this is the only way to hold a 'primary reference' to a
memory resource, although other references to this object may exist (aliases).

>I will say that if the style of programming and the common idioms in
>C++ are the same as in C, then Bjarne Stroustrup went to a lot of
>effort for nothing.  Of course, they're different.  (If you're getting
>the most out of C++, anyway.)
>

Right, there may be better idioms with C++, but the old ones worked
without rewriting any code as long as you didn't use exceptions. Now the
primary reference MUST be some kind of auto_ptr, otherwise the code will fail.


|> ...[The language] provides exceptions and it provides an
|> operator new, which is mainly used to initialize pointers. Both are fine in
|> own right. But if you want them to work together you have to supply constructs
|> which are not part of the language. Ok, you can use components of the standard
|> libraries, but these are NOT part of the language. IMHO, this leaves the
|> conclusion, that the language is incomplete to some point.
>
>I think the problem is because C++ addresses programming at all
>levels.  At the lowest level, where you are actually manipulating
>pointers and using new directly, exceptions should probably be
>avoided.  Thus, for example, an implementation of string or vector
>should probably *not* call a lot of complex functions that may throw
>exceptions.  At the levels where most of us work, however, it is new
>and pointer manipulation that will not be present.
>

I agree with you in principle, but I get the feeling that low level
support has been degraded by all those fancy high level features.
So we soon may reach the point, where C++ cannot be used by low level
programmers anymore, which would be a pity.

>Even at the lowest level, I see very little use for new except when
>the pointer is maintained by a class (which allows for clean-up in the
>destructor).
>

Well, this depends very much on the programming style. I like those
Object* p = new Object(somewhat); stuff quite a lot, and I think I'm not the
only one :-).

[...]
|> Now that's the point. Can we afford to throw away a huge amount of already
|> written software (using pointers the old way), because it will fail when
|> exceptions are introduced, or rather leave exceptions alone and stay with
|> the old libraries? If someone starts a project totally from scrap, fine.
|> But a lot of people may not have this choice, so they will not be able to use
|> exceptions for a long time (as I remember, it took more than a decade to get
|> some libraries ported from FORTRAN to C). Worse yet, in the future you may
|> not even be able to use new libraries, because they use exceptions. There may
|> be workarounds, of course, but this will involve a lot of work, which could have
|> been avoided.
>
>Well, exceptions were presented in the ARM, which is copyright 1990 or
>1991.  So we've already had 5 years to prepare.

Now be serious here. Exceptions were proposed then, but the first commercial
compilers that really supported them are not older than about 2 years.
(I think Watcom 9.5 was one of the first, and it worked awfully.)
I don't think, too many programmers had the foresight, to adopt to a
language feature, they could't even use.

>What worries me most isn't that the problems will be frequent, but
>that there is nothing that will signal them.  Programs with such
>problems will compile, and often pass most of the trivial tests, only
>to fail in the field.

As I stated above, this will be the real problem. And, given that exceptions
are a rather rare event, I wish good luck to everyone, who has to debug
these applications :-); even more, because undestroyed objects will most of the
time go undetected and cause no trouble, nevertheless they represent a bug.

What is really annoying me, is that this need not be so. It could have been
solved by introducing at least a 'poor man's garbage collection' at the same
time as exceptions. It had to run only after an exception was thrown.
I understand that this is is easier said than implemented, but it would have
reduced all the mentioned problems to void.

--
Bernhard Brunner             brn@iis.fhg.de






Author: brn@iis.fhg.de (Bernhard Brunner)
Date: 1995/05/16
Raw View
In article <KANZE.95May12110656@slsvhdt.lts.sel.alcatel.de>,
kanze@lts.sel.alcatel.de says...
[...]
>
>|> But let's think a bit further. The consequence of this approach is
>|> that you may NEVER create an object using new when you're not
>|> absolutely sure that there will be never thrown an exception until it
>|> is deleted again. This of course would nearly abandon pointers,
>|> because they were useable only as aliases to local or static variables.
>
>There are two solutions: the resource acquision is initialization
>idiom that you cite from D&E, and wrapping the code in a try block.
>

I did't say, it could not be done. There are quite a number of possible
solutions, and if it can be done in a standard way (I've read [lib.auto.ptr]
in the meantime, thanks :-) ), that's even better.
But anyway, pointers outside of an object will be reduced to pure aliases, which
may not be the single reference to any object. I think, this is a point which
should be mentioned, because it demands a style of programming, which is totally
different from the idioms used in C.

>As a general rule, I think that the resource acquision is
>initialization idiom is cleaner and easier to use.  But I wouldn't
>condemn anyone for using try blocks in this case.
>
>|> IMHO, exception handling, as proposed in the draft, and heavy use of
>|> pointers will not fit together as long as there isn't also some garbage
>|> collection involved. Don't get me wrong here, I'm no special friend of
>|> garbage collection, I just see no other solution, which is clean enough.
>|> Maybe I simply missed something, but if so, I would be glad if someone
>|> could enlighten me :-).
>
>In future code, I don't see this as a real problem.  As you say, heavy
>use of pointers (to the heap) and exceptions do not work well
>together.  In practice, though, I imagine that most of the current
>local dynamic allocations will be replaced with either string or
>vector.  A `new', used as in your example, will be rare outside of
>anything but the most low level code (and probably rare there).

You may be right, but I was looking for a CLEAN solution, and I'm not sure, if
this is one. Look what we have got now:
First there is the language itself. It provides exceptions and it provides an
operator new, which is mainly used to initialize pointers. Both are fine in their
own right. But if you want them to work together you have to supply constructs,
which are not part of the language. Ok, you can use components of the standard
libraries, but these are NOT part of the language. IMHO, this leaves the
conclusion, that the language is incomplete to some point.

>
>In the meantime...  I've already said it: exceptions *will* cause
>problems with a lot of existing code.  This is something that should
>be considered in your planning; when moving to exceptions, don't
>forget the effort necessary to upgrade old code.

Now that's the point. Can we afford to throw away a huge amount of already
written software (using pointers the old way), because it will fail when
exceptions are introduced, or rather leave exceptions alone and stay with
the old libraries? If someone starts a project totally from scrap, fine.
But a lot of people may not have this choice, so they will not be able to use
exceptions for a long time (as I remember, it took more than a decade to get
some libraries ported from FORTRAN to C). Worse yet, in the future you may
not even be able to use new libraries, because they use exceptions. There may
be workarounds, of course, but this will involve a lot of work, which could have
been avoided.


--
Bernhard Brunner             brn@iis.fhg.de






Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/05/17
Raw View
In article <3pa3d5$dmq@iis.iis.fhg.de> brn@iis.fhg.de (Bernhard
Brunner) writes:

|> In article <KANZE.95May12110656@slsvhdt.lts.sel.alcatel.de>,
|> kanze@lts.sel.alcatel.de says...
|> [...]
|> >
|> >|> But let's think a bit further. The consequence of this approach is
|> >|> that you may NEVER create an object using new when you're not
|> >|> absolutely sure that there will be never thrown an exception until it
|> >|> is deleted again. This of course would nearly abandon pointers,
|> >|> because they were useable only as aliases to local or static variables.
|> >
|> >There are two solutions: the resource acquision is initialization
|> >idiom that you cite from D&E, and wrapping the code in a try block.
|> >

|> I did't say, it could not be done. There are quite a number of possible
|> solutions, and if it can be done in a standard way (I've read [lib.auto.ptr]
|> in the meantime, thanks :-) ), that's even better.
|> But anyway, pointers outside of an object will be reduced to pure aliases, which
|> may not be the single reference to any object. I think, this is a point which
|> should be mentioned, because it demands a style of programming, which is totally
|> different from the idioms used in C.

I don't understand what you are trying to say: "pointers outside of an
object will be reduced to pure aliases.  Do you mean that the standard
class does not support pointer arithmetic?  (I'm tempted to say that
this would be a good thing.)

I will say that if the style of programming and the common idioms in
C++ are the same as in C, then Bjarne Stroustrup went to a lot of
effort for nothing.  Of course, they're different.  (If you're getting
the most out of C++, anyway.)

|> >As a general rule, I think that the resource acquision is
|> >initialization idiom is cleaner and easier to use.  But I wouldn't
|> >condemn anyone for using try blocks in this case.
|> >
|> >|> IMHO, exception handling, as proposed in the draft, and heavy use of
|> >|> pointers will not fit together as long as there isn't also some garbage
|> >|> collection involved. Don't get me wrong here, I'm no special friend of
|> >|> garbage collection, I just see no other solution, which is clean enough.
|> >|> Maybe I simply missed something, but if so, I would be glad if someone
|> >|> could enlighten me :-).
|> >
|> >In future code, I don't see this as a real problem.  As you say, heavy
|> >use of pointers (to the heap) and exceptions do not work well
|> >together.  In practice, though, I imagine that most of the current
|> >local dynamic allocations will be replaced with either string or
|> >vector.  A `new', used as in your example, will be rare outside of
|> >anything but the most low level code (and probably rare there).

|> You may be right, but I was looking for a CLEAN solution, and I'm not sure, if
|> this is one.

What could be cleaner than using high-level types instead of machine
level types?

|> Look what we have got now:
|> First there is the language itself. It provides exceptions and it provides an
|> operator new, which is mainly used to initialize pointers. Both are fine in their
|> own right. But if you want them to work together you have to supply constructs,
|> which are not part of the language. Ok, you can use components of the standard
|> libraries, but these are NOT part of the language. IMHO, this leaves the
|> conclusion, that the language is incomplete to some point.

I think the problem is because C++ addresses programming at all
levels.  At the lowest level, where you are actually manipulating
pointers and using new directly, exceptions should probably be
avoided.  Thus, for example, an implementation of string or vector
should probably *not* call a lot of complex functions that may throw
exceptions.  At the levels where most of us work, however, it is new
and pointer manipulation that will not be present.

Even at the lowest level, I see very little use for new except when
the pointer is maintained by a class (which allows for clean-up in the
destructor).

|> >In the meantime...  I've already said it: exceptions *will* cause
|> >problems with a lot of existing code.  This is something that should
|> >be considered in your planning; when moving to exceptions, don't
|> >forget the effort necessary to upgrade old code.

|> Now that's the point. Can we afford to throw away a huge amount of already
|> written software (using pointers the old way), because it will fail when
|> exceptions are introduced, or rather leave exceptions alone and stay with
|> the old libraries? If someone starts a project totally from scrap, fine.
|> But a lot of people may not have this choice, so they will not be able to use
|> exceptions for a long time (as I remember, it took more than a decade to get
|> some libraries ported from FORTRAN to C). Worse yet, in the future you may
|> not even be able to use new libraries, because they use exceptions. There may
|> be workarounds, of course, but this will involve a lot of work, which could have
|> been avoided.

Well, exceptions were presented in the ARM, which is copyright 1990 or
1991.  So we've already had 5 years to prepare.

Interestingly enough, if you use the common C++ idioms, instead of
just writing C, you probably don't have that many problems.  I
recently took a look at some code that I wrote before I every heard of
exceptions; it all turned out to be exception safe anyway.  (A bit of
luck helped, no doubt.)

If you are still using new for run-time sized arrays and char* for
strings, you will probably have problems.

What worries me most isn't that the problems will be frequent, but
that there is nothing that will signal them.  Programs with such
problems will compile, and often pass most of the trivial tests, only
to fail in the field.
--
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: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/05/12
Raw View
In article <3oqmg4$j57@iis.iis.fhg.de> brn@iis.fhg.de (Bernhard
Brunner) writes:

|> Looking at the actual working paper, I think there is a general problem
|> with exceptions and pointers.
|> Take the following piece of code:

|> void f(); // may throw any exception
|>           // note that f() throw (something) would work the same way

|> void g()
|> {
|>   SomeClass* p = new SomeClass;
|>   f();   // throws exception
|>   delete p;  // never reached, *p not destroyed
|> }

|> This may seem trivial at the first glance and could be solved by
|> replacing 'p' by a automatic variable, say of class SomeClassPtr.
|> An example dealing with file resources is given within D&E of C++,
|> chapter about exceptions (I have no copy at hand, so I cannot be
|> more specific at the moment).

|> But let's think a bit further. The consequence of this approach is
|> that you may NEVER create an object using new when you're not
|> absolutely sure that there will be never thrown an exception until it
|> is deleted again. This of course would nearly abandon pointers,
|> because they were useable only as aliases to local or static variables.

There are two solutions: the resource acquision is initialization
idiom that you cite from D&E, and wrapping the code in a try block.

As a general rule, I think that the resource acquision is
initialization idiom is cleaner and easier to use.  But I wouldn't
condemn anyone for using try blocks in this case.

|> IMHO, exception handling, as proposed in the draft, and heavy use of
|> pointers will not fit together as long as there isn't also some garbage
|> collection involved. Don't get me wrong here, I'm no special friend of
|> garbage collection, I just see no other solution, which is clean enough.
|> Maybe I simply missed something, but if so, I would be glad if someone
|> could enlighten me :-).

In future code, I don't see this as a real problem.  As you say, heavy
use of pointers (to the heap) and exceptions do not work well
together.  In practice, though, I imagine that most of the current
local dynamic allocations will be replaced with either string or
vector.  A `new', used as in your example, will be rare outside of
anything but the most low level code (and probably rare there).

In the meantime...  I've already said it: exceptions *will* cause
problems with a lot of existing code.  This is something that should
be considered in your planning; when moving to exceptions, don't
forget the effort necessary to upgrade old code.
--
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/05/12
Raw View
Bernhard Brunner (brn@iis.fhg.de) wrote:
: Looking at the actual working paper, I think there is a general problem
: with exceptions and pointers.
: Take the following piece of code:

: void f(); // may throw any exception
:           // note that f() throw (something) would work the same way

: void g()
: {
:   SomeClass* p = new SomeClass;
:   f();   // throws exception
:   delete p;  // never reached, *p not destroyed
: }

: This may seem trivial at the first glance and could be solved by
: replacing 'p' by a automatic variable, say of class SomeClassPtr.
: An example dealing with file resources is given within D&E of C++,
: chapter about exceptions (I have no copy at hand, so I cannot be
: more specific at the moment).

Have a look at the auto_ptr class ([lib.auto_ptr] page 20-17) - this
provides a utility class that 'owns' a pointer.


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





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/14
Raw View
In article <3oqmg4$j57@iis.iis.fhg.de>,
Bernhard Brunner <brn@iis.fhg.de> wrote:
>Looking at the actual working paper, I think there is a general problem
>with exceptions and pointers.
>Take the following piece of code:
>
>void f(); // may throw any exception
>          // note that f() throw (something) would work the same way
>
>void g()
>{
>  SomeClass* p = new SomeClass;
>  f();   // throws exception
>  delete p;  // never reached, *p not destroyed
>}
>

 void g() {
  auto_ptr<SomeClass> p(new SomeClass);
  f();
 }

object destroyed by unwinding the stack whether or not f()
throws an exception.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/05/11
Raw View
In article j57@iis.iis.fhg.de, brn@iis.fhg.de (Bernhard Brunner) writes:
>Looking at the actual working paper, I think there is a general problem
>with exceptions and pointers.
>Take the following piece of code:
>
>void f(); // may throw any exception
>          // note that f() throw (something) would work the same way
>
>void g()
>{
>  SomeClass* p = new SomeClass;
>  f();   // throws exception
>  delete p;  // never reached, *p not destroyed
>}

Correct. This situation is covered in most good C++ texts, which
advocate something like the "resource acquisition is initialization"
model. The draft standard even includes a standard template which
makes this easy to deal with:

"[lib.auto.ptr] 20.4.5 Template class auto_ptr.
Template auto_ptr holds onto a pointer obtained via new and deletes that
object when it itself is destroyed (such as when leaving block scope 6.7)."

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







Author: brn@iis.fhg.de (Bernhard Brunner)
Date: 1995/05/10
Raw View
Looking at the actual working paper, I think there is a general problem
with exceptions and pointers.
Take the following piece of code:

void f(); // may throw any exception
          // note that f() throw (something) would work the same way

void g()
{
  SomeClass* p = new SomeClass;
  f();   // throws exception
  delete p;  // never reached, *p not destroyed
}

This may seem trivial at the first glance and could be solved by
replacing 'p' by a automatic variable, say of class SomeClassPtr.
An example dealing with file resources is given within D&E of C++,
chapter about exceptions (I have no copy at hand, so I cannot be
more specific at the moment).

But let's think a bit further. The consequence of this approach is
that you may NEVER create an object using new when you're not
absolutely sure that there will be never thrown an exception until it
is deleted again. This of course would nearly abandon pointers,
because they were useable only as aliases to local or static variables.

IMHO, exception handling, as proposed in the draft, and heavy use of
pointers will not fit together as long as there isn't also some garbage
collection involved. Don't get me wrong here, I'm no special friend of
garbage collection, I just see no other solution, which is clean enough.
Maybe I simply missed something, but if so, I would be glad if someone
could enlighten me :-).


--
Bernhard Brunner             brn@iis.fhg.de