[Insight-developers] serious problem with new[] on MSVC++
Brad King
brad.king at kitware.com
Thu, 25 Mar 2004 09:43:48 -0500
Charl P. Botha wrote:
> Dear developers,
>
> It seems that, at least on MSVC, new (or new[]) does not throw an
> exception when failing to allocate memory[1][2]. Looking at for
> instance itk::ImportImageContainer::Reserve(), which does all the
> allocation for itk::Image (and thus for MANY of the ITK filters and
> sources), the return value of the new[] is not checked!
>
> I've seen this crash my applications on windows when working with large
> DICOM datasets. The program silently continues running, until a filter
> writes to for example the output Image which has a NULL buffer (due to a
> failed new[] that wasn't caught).
>
> This can be fixed by installing a global new_handler function[3]. I've
> grepped through the ITK sources and couldn't find an invocation of
> _set_new_handler(), so I'm assuming no-one has done this.
>
> Any discussion (or corrections!) on this is welcome. I'm not sure how
> new[] indicates failure on for instance the GCC compilers, but whatever
> the case may be, it's quite critical that this is handled *correctly* in
> ITK. The ISO C++ spec says that new[] should throw (as far as I can
> see), but compilers don't always follow this to the letter, as is shown
> by this example.
The C++ standard says that if a new or new[] operator is declared with
an empty "throw()" specification then it should return NULL when failing
to allocate memory. Otherwise it should throw a std::bad_alloc exception.
ITK has been written to assume that the exception is thrown and
therefore never checks the results of allocation (which is the whole
point of a throwing allocation routine). However, ITK should not set
anything that is of global process scope since it is a library. The
application should set the handler correctly if it wants to be robust to
this problem.
Another alternative is to send all ITK memory allocation through some
function that tries to use new or new[] to alloate memory and then
throws std::bad_alloc if it gets a NULL pointer back. That way we can
be sure the exception will be thrown no matter the default behavior
provided by a compiler.
-Brad