Topic: Portable Use of New
Author: sjm@cae.co.uk
Date: 1999/05/13 Raw View
> > > To combat any vendor supplied 'new' that merely exits upon
allocation
> > > failure, can we not replace the standard library 'new' (by
including
> > > it in the link before pulling in the standard libraries)? What
are the
> > > consequences of doing this? (e.g. will library code - using our
version
> > > of new - still propagate an exception if it is throw internally
to it,
> >
> > Yes
>
> Attention. If the library code was written with this compiler in
mind,
> it may assume that new doesn't throw, and it may not be thread safe.
> Changing the semantics of the global new is dangerous business. About
> the only time I'd dare such a thing is when adding debugging
information
> (which won't be in the delivered version).
>
> [Moderator note: s/thread safe/exception safe/ ? --vb]
>
> > > Any comments? Any pitfalls? Any improvements?
> > > I cannot be the only one striving to write highly portable
> > > code...
> >
> > I think your idea above is the best one. Forget macros and all of
the other
> > mess. The reason you're having portability problems is that you're
trying to
> > work with out-of-date compilers (try egcs instead of gcc). If you
can't get
> > a C++ implementation that's more standard-compliant, supply your
own global
> > operator new which does the job right, by throwing bad_alloc if an
> > allocation fails (after calling the new-handler, etc.).
>
> There are different levels of "out-of-date". If the compiler in
> question simply throws xalloc, instead of bad_alloc, your suggestion
is
> probably OK. If the compiler returns NULL instead of throwing an
> exception, however, changing it to throw will probably break all of
the
> system libraries, which don't expect new to throw and so aren't
> exception safe. And if the compiler simply aborts when there is no
more
> memory, IMHO, there is nothing you can do that won't break the system
> libraries: they expect a valid value back from new, and are probably
not
> thread safe.
>
Ok, so suppose I'm building a library of portable classes. What are the
pros and cons of the following approach.
1) For any use of new of an intrinsic (or externally sourced) class, I
(always) do the following:
class OutOfMemory{};
MyClass::foo()
{
....
try { p = new Thing( 42 ) }
catch( int ) { p = NULL; } // a sole (...) rejected by some
compilers.
catch( ... ) { p = NULL; }
if ( p == NULL )
{
throw OutOfMemory;
}
}
2) I always abstract from third party stuff by defining my own access
classes (defined with their *own* behavioural interface, to which the
third party libraries map). So I alway build *upon* these, providing a
single-point of entry to all future code I write (minimising
dependencies upon other sources of code).
3) For every class that *I* write, I ensure that the new semantics are
to throw OutOfMemory, by having a policy for *every* such class to
overload the new operator to provide this behaviour.
Does this satisfy the objective entirely? Does anyone see any pitfalls?
I know it doesn't handle the "exit of new failure" standard library
behaviour (should the compiler do that). However, I do not have to
write any code to cope with that situation anyway as no more of my code
would be executed after that point.
--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Dave Abrahams <abrahams@mediaone.net>
Date: 1999/05/09 Raw View
In article <7gu7l6$mk3$1@nnrp1.deja.com> , James.Kanze@dresdner-bank.com
wrote:
> In article <WleY2.603$AL5.1209@ndnws01.ne.mediaone.net>,
> "Dave Abrahams" <abrahams@mediaone.net> wrote:
>> In article <7gpjfo$h6c$1@nnrp1.dejanews.com> , sjm@cae.co.uk wrote:
>>
>> > To combat any vendor supplied 'new' that merely exits upon allocation
>> > failure, can we not replace the standard library 'new' (by including
>> > it in the link before pulling in the standard libraries)? What are the
>> > consequences of doing this? (e.g. will library code - using our version
>> > of new - still propagate an exception if it is throw internally to it,
>>
>> Yes
>
> Attention. If the library code was written with this compiler in mind,
> it may assume that new doesn't throw, and it may not be thread safe.
> Changing the semantics of the global new is dangerous business. About
> the only time I'd dare such a thing is when adding debugging information
> (which won't be in the delivered version).
James is right. I must have been typing on auto-pilot. It might not be so
terribly dangerous to make the replacement (for your code), but if you throw
through a library which was written to assume new would abort(), there's no
reason to assume it would work properly.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Dave Abrahams" <abrahams@mediaone.net>
Date: 1999/05/06 Raw View
In article <7gpjfo$h6c$1@nnrp1.dejanews.com> , sjm@cae.co.uk wrote:
> To combat any vendor supplied 'new' that merely exits upon allocation
> failure, can we not replace the standard library 'new' (by including
> it in the link before pulling in the standard libraries)? What are the
> consequences of doing this? (e.g. will library code - using our version
> of new - still propagate an exception if it is throw internally to it,
Yes
> Any comments? Any pitfalls? Any improvements?
> I cannot be the only one striving to write highly portable
> code...
I think your idea above is the best one. Forget macros and all of the other
mess. The reason you're having portability problems is that you're trying to
work with out-of-date compilers (try egcs instead of gcc). If you can't get
a C++ implementation that's more standard-compliant, supply your own global
operator new which does the job right, by throwing bad_alloc if an
allocation fails (after calling the new-handler, etc.).
-Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Biju Thomas <b_thomas@ibm.net>
Date: 1999/05/06 Raw View
sjm@cae.co.uk wrote:
>
>
> Thing* thing;
>
> try { thing = new Thing( 42 ); }
> catch( int ) { thing = NULL; } // can't catch only ...
> catch( ... ) { thing = NULL; }
>
You mean that I can't have a single 'catch(...)' clause? I haven't heard
of such a limitation in any compiler.
--
Biju Thomas
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/05/07 Raw View
In article <WleY2.603$AL5.1209@ndnws01.ne.mediaone.net>,
"Dave Abrahams" <abrahams@mediaone.net> wrote:
> In article <7gpjfo$h6c$1@nnrp1.dejanews.com> , sjm@cae.co.uk wrote:
>
> > To combat any vendor supplied 'new' that merely exits upon allocation
> > failure, can we not replace the standard library 'new' (by including
> > it in the link before pulling in the standard libraries)? What are the
> > consequences of doing this? (e.g. will library code - using our version
> > of new - still propagate an exception if it is throw internally to it,
>
> Yes
Attention. If the library code was written with this compiler in mind,
it may assume that new doesn't throw, and it may not be thread safe.
Changing the semantics of the global new is dangerous business. About
the only time I'd dare such a thing is when adding debugging information
(which won't be in the delivered version).
[Moderator note: s/thread safe/exception safe/ ? --vb]
> > Any comments? Any pitfalls? Any improvements?
> > I cannot be the only one striving to write highly portable
> > code...
>
> I think your idea above is the best one. Forget macros and all of the other
> mess. The reason you're having portability problems is that you're trying to
> work with out-of-date compilers (try egcs instead of gcc). If you can't get
> a C++ implementation that's more standard-compliant, supply your own global
> operator new which does the job right, by throwing bad_alloc if an
> allocation fails (after calling the new-handler, etc.).
There are different levels of "out-of-date". If the compiler in
question simply throws xalloc, instead of bad_alloc, your suggestion is
probably OK. If the compiler returns NULL instead of throwing an
exception, however, changing it to throw will probably break all of the
system libraries, which don't expect new to throw and so aren't
exception safe. And if the compiler simply aborts when there is no more
memory, IMHO, there is nothing you can do that won't break the system
libraries: they expect a valid value back from new, and are probably not
thread safe.
--
James Kanze mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orientie objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelh|ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86 27
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sjm@cae.co.uk
Date: 1999/05/05 Raw View
MarceloChaves@hotmail.com wrote:
>>
>> Gentlepeople,
>>
>> I noticed that diferent C++ compilers implement different actions when a
>> memory allocation via new fails. For example, the g++ (gnu) compiler (Linux)
>> aborts in case the (internal) malloc fails (it printfs and aborts); some
>> compilers raise an exception (I guess an old Borland compiler used something
>> called "xlalloc"), according Bjarne's C++ reference book, the new operator
>> should return NULL ( (void *) 0), and so on.> > Does anybody know:>
>> a) Which should be the standard behaviour in case new fails? b) How the best
>> way to write portable code using new (override new operator? use of malloc +
>> placement new? go back to malloc??) c) Am I missing something here? :-)
>
> a): Section 3.7.3.1, p3:
> "An allocation function that fails to allocate storage can invoke the
> currently installed new_handler (18.4.2.2), if any [Note: A
> program-supplied allocation function can obtain the address of the
> currently installed new_handler using the set_new_handler function
> (18.4.2.3).] If an allocation function declared with an empty
> exception-specification (15.4), throw(), fails to allocate storage, it
> shall return a null pointer. Any other allocation function that fails to
> allocate storage shall only indicate failure by throwing an exception of
> class std::bad_alloc(18.4.2.1) or a class derived from std::bad_alloc."
> Seciton 5.3.4p13 adds:
>
> "If the allocation function returns null, initialization shall not be
> done, the deallocation function shall not be called, and the value of
> the new-expression shall be null."
> You can use the non-throwing version by using 'new(nothrow)'.
>
> b) There's no way you can guarantee portability to arbitrary
> implementations that haven't yet implemented the standard. The best you
> can do is see what works on the implementations you actually need to
> port to. Sorry.
No way to guarantee portability? Well, sometimes you *need* it - e.g. if
you're responsible for creating reusable source code. Instead of...
Thing* thing;
thing = new Thing( 42 );
which could return NULL on failure, or throw xalloc, bad_alloc, etc. on
failure (whatever the currently used compiler might actually do is what
we have to copw with). So why not instead do the following...
Thing* thing;
try { thing = new Thing( 42 ); }
catch( int ) { thing = NULL; } // can't catch only ...
catch( ... ) { thing = NULL; }
if ( thing = NULL ) // ...the allocation failed.
Won't this work whatever the compiler does? the above can be generalised and
encapsulated as a macro.
# define MyNew( p, C ) \
{ \
try { p = new C; } \
catch ( int ) { p = NULL; } \
catch ( ... ) { p = NULL; } \
}
...so that we use...
Thing* thing;
MyNew( thing, Thing( 42 ) );
We use a macro, because we need the lexical flexibility in specifying
the constructor after the "new".
The only problem with this is that it doesnt distinquish between an
*allocation* exception and any *construction* exception. Also, as has
been already pointed out, some compilers simply exit upon an allocation
failure.
In order to combat (some of) this, can't we use the above macro when
allocating third-party defined objects, but for our own-defined classes
always provide an operator new (with defined behaviour for allocation
failure, such as throwing OutOfMemory), and then merely use the standard
method for allocation *only* for *our* classes. e.g
MyClass* thing;
try { thing = new MyClass( 42 ); }
catch ( /* whatever our class might throw on constructon */ ) { ..... }
catch ( OutOfMemory& ) { /* allocation failure specific handler */ }
SomeoneElsesClass* otherThing;
MyNew( otherThing, SomeoneElsesClass( 1, 2, 3 ) );
if ( otherTHing = NULL ) // ...failed allocation
For consistency, we could make the macro throw the same exception...
# define MyNew( p, C ) \
{ \
try { p = new C; } \
catch ( int ) { p = NULL; } \
catch ( ... ) { p = NULL; } \
if ( p = NULL ) throw OutOfMemory;
}
To combat any vendor supplied 'new' that merely exits upon allocation
failure, can we not replace the standard library 'new' (by including
it in the link before pulling in the standard libraries)? What are the
consequences of doing this? (e.g. will library code - using our version
of new - still propagate an exception if it is throw internally to it,
or fail to do so...?)
Any comments? Any pitfalls? Any improvements?
I cannot be the only one striving to write highly portable
code...
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]