You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-dev@xerces.apache.org by Miroslaw Dobrzanski-Neumann <mn...@mosaic-ag.com> on 2000/10/31 15:43:07 UTC

even more crashes

Hi,
its me again.

It turns out that there is no plausibility check in the interface presented to
the user. Simple method calls on null node causes application crash i.e.

DOM_Node node;
node.normalize();
	boing!!!

Notice: I use no pointer, I see no pointer.

Me as fool end user expect a foolproof interface. I can catch an exception but
not a program crash.

Re: even more crashes

Posted by Miroslaw Dobrzanski-Neumann <mn...@mosaic-ag.com>.
If you have already developed some pice of software for AIX systems (as most
of you IBM guys) you will know the fact that AIX DOES NOT PREVENT you from
accessing the null page where the NULL lives.
try the following (I use the native tools: AIX => xlC):

#include <fstream.h>
int main(int, char*[])
{
	        void** ptr = NULL;
	        cerr<<"ptr = "<<ptr<<", *ptr = "<<*ptr<<endl;
	        return 0;
}

the output for all AIX4 versions (41,42,43)
ptr = 0x0, *ptr = 0x0

Notice:
The application must not crash at this point (not on AIX) => not to check for
NULL pointer if you know it can become NULL is a coding error.


Here the much better solution for this problem
==============================================
taken from Jame O. Coplien "Advanced C++ Programming Styles and Idioms"

in the attachment you find an sample.
the assignment and copy ctor does not work because not implemented

the key point is:
1. You define vtbl as an array of function pointers all pointing to an error
   handler which i.e. throw an exception or calls abort() or ...
   the array must be large enough to hold all entry points for virtual
   functions in derived classes.
2. You define void* var and let it point to this table (its your null object)
3. You define void** and let it point to null object
4. instead of assigning NULL to fimpl you assign null object
   instead of checking for NULL you check for null object
5. from now all works fine and efficient. it is not required to check for NULL
   before call to any virtual method because you have a generic null object
   which handles this erronous case.

It may look like a dirty C hack but it is not. It is a clean and short
solution for this kind of errors
--
Miroslaw Dobrzanski-Neumann

MOSAIC SOFTWARE AG
Base Development and Research
Tel +49-2225-882-291
Fax +49-2225-882-201
E-mail: mne@mosaic-ag.com

Re: even more crashes

Posted by John Ky <ha...@syd.speednet.com.au>.
> Me as fool end user expect a foolproof interface. I can
> catch an exception but not a program crash.

Your not the only person to do something like that.
Two cents worth of comment from yours truly.

If a foolproof interface doesn't make the system more
secure, it isn't worth doing.  Defensive programming
is normally regarded as poor programming practise
in any case.  You should consider operations on null
references as violating Xerces' contract and simply
not do it.  Design by Contract makes for cleaner
more efficient code.

And this is from someone who's application crashed
in the same way before.  The way I think of it:
my application crashed - not Xerces.

    if (node == 0)

isn't that hard to do.

It would be nice to be able to do this though:

    if (!node)

That's the way I've tested for NULL all my life.
Brevity is a good thing IMO.

But I disgress.

Thanks

-John



Re: even more crashes

Posted by Andy Heninger <an...@jtcsv.com>.
"Miroslaw Dobrzanski-Neumann" <mn...@mosaic-ag.com> writes

> It turns out that there is no plausibility check in the interface
presented to
> the user. Simple method calls on null node causes application crash i.e.
>
> DOM_Node node;
> node.normalize();
> boing!!!
>
> Notice: I use no pointer, I see no pointer.


A good part of the confusion comes from the fact that the
Xerces-c DOM API is modeled after Java, and isn't always
quite what might be first expected in C++.

The exact statements shown above would compile fine and
give the same null pointer runtime exception in Java when
using the official W3C DOM bindings for Java (except for the
class name being just plain Node rather than DOM_Node).

Andy Heninger
IBM XML Technology Group, Cupertino, CA
heninger@us.ibm.com



Re: even more crashes

Posted by Hal DeVore <ha...@acm.org>.
>>>>> On Thu, 2 Nov 2000, "Jojakim" == Jojakim Stahl wrote:

  Jojakim> I only tried to point out that if a programmer looks
  Jojakim> at a line with node.function() syntax on the first
  Jojakim> view doesn't expect a NullPointerException be raised
  Jojakim> as an response to a NULL reference.

I think that would depend on the programmer and how much he or
she had been using references.  References == pointers for all
intents and purposes.


--Hal



RE: even more crashes

Posted by Jojakim Stahl <js...@inpra.de>.
In general you are right and I don't want you to add "if (!ref)" checks to
Xerces. And I agree that it is better to have an app die as response to
invalid calls or other malformed execution at development time. I only tried
to point out that if a programmer looks at a line with node.function()
syntax on the first view doesn't expect a NullPointerException be raised as
an response to a NULL reference.

But if you would have to use the node->function() syntax it would be obious
to almost every programmer that *he* has to check for NULL references and
that they may occure at all.

Joja

> -----Original Message-----
> From: John Ky [mailto:hand@syd.speednet.com.au]
> Sent: Wednesday, November 01, 2000 5:34 AM
> To: xerces-c-dev@xml.apache.org
> Subject: Re: even more crashes
>
>
> > As one uses the . operator instead of ->, it implicates that you have
> > actually an object where you are calling on, and no reference. By
> internally
> > using a reference (actually only calling something like ref->normalize()
> > from node.normalize()), in my opinion Xerces gets responsible for doing
> the
> > if (!ref) check.
>
> And what would you have done in when if (!ref) holds true?
>
> > At all, the node variable is not declared as a C++ reference
> and therefore
> > in normal circumstances would always be a valid object and no
> one expects
> a
> > Null-Pointer-Exception by calling a method on it.
>
> Initialisation errors should always be caught early and dying
> would do more
> good than either doing nothing or throwing an exception because
> that forces
> the programmer to check that the code is infact correct.
>
> There is nothing worse than a programmer forgetting to initialise the node
> object and calling it as if it was initialised.  Xerces does what's best
> IMO,
> because these programming errors are hard to catch.
>
> NullPointerExceptions are almost always programming errors - why
> should they succeed in any way?
>
> What are ASSERTIONS for anyway?  Don't people use it to make
> their applications die in development rather than production release?
>
> The only "if (!ref)" check that should be performed by Xerces IMO,
> would be to formalise the fact that the operation is invalid:
>
> ASSERT(fImpl != 0);
>
> Perhaps no one is responsible for knowing a function call causes
> a NullPointerExeption.  But they are certainly responsible for
> using an API correctly.  Xerces does programmers a service
> by dying when it knows it has been called incorrectly and by
> providing a means to check preconditions ie if (node ==
> NULL).  Making assumptions about how users want errors
> handled is the worst Xerces can do.
>
> -John
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: xerces-c-dev-unsubscribe@xml.apache.org
> For additional commands, e-mail: xerces-c-dev-help@xml.apache.org
>


Re: even more crashes

Posted by John Ky <ha...@syd.speednet.com.au>.
> As one uses the . operator instead of ->, it implicates that you have
> actually an object where you are calling on, and no reference. By
internally
> using a reference (actually only calling something like ref->normalize()
> from node.normalize()), in my opinion Xerces gets responsible for doing
the
> if (!ref) check.

And what would you have done in when if (!ref) holds true?

> At all, the node variable is not declared as a C++ reference and therefore
> in normal circumstances would always be a valid object and no one expects
a
> Null-Pointer-Exception by calling a method on it.

Initialisation errors should always be caught early and dying would do more
good than either doing nothing or throwing an exception because that forces
the programmer to check that the code is infact correct.

There is nothing worse than a programmer forgetting to initialise the node
object and calling it as if it was initialised.  Xerces does what's best
IMO,
because these programming errors are hard to catch.

NullPointerExceptions are almost always programming errors - why
should they succeed in any way?

What are ASSERTIONS for anyway?  Don't people use it to make
their applications die in development rather than production release?

The only "if (!ref)" check that should be performed by Xerces IMO,
would be to formalise the fact that the operation is invalid:

ASSERT(fImpl != 0);

Perhaps no one is responsible for knowing a function call causes
a NullPointerExeption.  But they are certainly responsible for
using an API correctly.  Xerces does programmers a service
by dying when it knows it has been called incorrectly and by
providing a means to check preconditions ie if (node ==
NULL).  Making assumptions about how users want errors
handled is the worst Xerces can do.

-John



RE: even more crashes

Posted by Jojakim Stahl <js...@inpra.de>.
> DOM_Node node;
> node.normalize();
> 	boing!!!
>
> Notice: I use no pointer, I see no pointer.


As one uses the . operator instead of ->, it implicates that you have
actually an object where you are calling on, and no reference. By internally
using a reference (actually only calling something like ref->normalize()
from node.normalize()), in my opinion Xerces gets responsible for doing the
if (!ref) check.

The only way I know about to get an Access-Violation or
Null-Pointer-Exception or Program Crash by using the object.member syntax is
to declare and init object as follows:
ObjectType& object = *((ObjectType*) 0);
or
ObjectType* objectPtr = 0;
ObjectType& object = *objectPtr;
Which seems pretty uncommon to me.

At all, the node variable is not declared as a C++ reference and therefore
in normal circumstances would always be a valid object and no one expects a
Null-Pointer-Exception by calling a method on it.

-- Joja