Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Knowing the implementation, are all undefined behaviours become implementation-defined behaviours?

Reply
Thread Tools

Knowing the implementation, are all undefined behaviours become implementation-defined behaviours?

 
 
Michael Tsang
Guest
Posts: n/a
 
      02-14-2010
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Deferencing a NULL pointer is undefined behaviour, but, on Linux, the
program crashes with SIGSEGV. So, the behaviour of derefencing a NULL
pointer is defined to "crash the program with SIGSEGV".

Signed integer overflow is undefined behaviour, but, on x86 CPUs, the number
simply wrap around so we can say that the behaviour is defined to round on
x86 CPUs.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkt3kjsACgkQm4klUUKw07D7QwCfQH0jkVFEDA QMi9+t31JiQ449
4QMAn2M+QxWW3yf4WShHgmWjBCluBvun
=e8V1
-----END PGP SIGNATURE-----

 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-14-2010
* Michael Tsang:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Deferencing a NULL pointer is undefined behaviour, but, on Linux, the
> program crashes with SIGSEGV. So, the behaviour of derefencing a NULL
> pointer is defined to "crash the program with SIGSEGV".
>
> Signed integer overflow is undefined behaviour, but, on x86 CPUs, the number
> simply wrap around so we can say that the behaviour is defined to round on
> x86 CPUs.
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAkt3kjsACgkQm4klUUKw07D7QwCfQH0jkVFEDA QMi9+t31JiQ449
> 4QMAn2M+QxWW3yf4WShHgmWjBCluBvun
> =e8V1
> -----END PGP SIGNATURE-----
>


Your question, from the subject line, is

"Knowing the implementation, are all undefined behaviours become
implementation-defined behaviours?"

And it's cross-posted to [comp.lang.c] and [comp.lang.c++].

At least for C++ the answer is a definite maybe: theoretically it depends on the
implementation.

In practice the answer is a more clear "no", because it's practically impossible
for an implementation to clearly define all behaviors, in particular pointer
operations and use of external libraries.



Cheers & hth.,

- Alf
 
Reply With Quote
 
 
 
 
Seebs
Guest
Posts: n/a
 
      02-14-2010
On 2010-02-14, Michael Tsang <(E-Mail Removed)> wrote:
> Deferencing a NULL pointer is undefined behaviour, but, on Linux, the
> program crashes with SIGSEGV. So, the behaviour of derefencing a NULL
> pointer is defined to "crash the program with SIGSEGV".


Not necessarily.

> Signed integer overflow is undefined behaviour, but, on x86 CPUs, the number
> simply wrap around so we can say that the behaviour is defined to round on
> x86 CPUs.


That's not rounding, that's wrapping.

But no, it's not the case. These are not necessarily *defined* -- they may
merely be typical side-effects that are not guaranteed or supported.

Modern gcc can do some VERY strange things if you write code which might
dereference a null pointer. (For instance, loops which check whether a
pointer is null may have the test removed because, if it were null, it
would have invoked undefined behavior to dereference it...)

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / http://www.velocityreviews.com/forums/(E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      02-14-2010
On Feb 14, 8:03*am, Michael Tsang <(E-Mail Removed)> wrote:
>

"Undefined behaviour" doesn't mean "exists in some metaphysical state
of indefiniteness" but "the C standard imposes no requirements on the
program's behaviour (and therefore the program is incorrect)". There
was a huge thread about this a few years back on gets.

So typically derefencing null will have the same effect each time any
particular program is run, probably the same effect on any particular
platform. Derefencing a wild pointer may have different effects,
particularly on a multi-taskign machine where exact pointer vlaues
vary from runto run.

 
Reply With Quote
 
Robert Fendt
Guest
Posts: n/a
 
      02-14-2010
And thus spake Seebs <(E-Mail Removed)>
14 Feb 2010 07:03:57 GMT:

> dereference a null pointer. (For instance, loops which check whether a
> pointer is null may have the test removed because, if it were null, it
> would have invoked undefined behavior to dereference it...)


Sorry to interrupt, but since when is checking a pointer value
for 0 the same as deferencing it? Checking a pointer treats the
pointer itself as a value, and comparison against 0 is one of
the few things that are _guaranteed_ to work with a pointer
value. So if GCC really would remove a check of the form

if(!pointer)
do_something(*pointer);

or even

if(pointer == 0)
throw NullPointerException;

then GCC would be very much in violation of the standard. And
produce absolutely useless code, as well. What's the point of
having pointers in a language if you wouldn't even be able to
perform basic operations on them?

Regards,
Robert

 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-14-2010
* Richard Heathfield:
> Michael Tsang wrote:
>> Deferencing a NULL pointer is undefined behaviour, but, on Linux, the
>> program crashes with SIGSEGV. So, the behaviour of derefencing a NULL
>> pointer is defined to "crash the program with SIGSEGV".

>
> Thread's subject line: Knowing the implementation, are all undefined
> behaviours become implementation-defined behaviours?
>
> No. For example, consider a stack exploit on gets(). There are systems
> on which the behaviour could be absolutely anything at all, depending on
> user input!6\b$10be5c39no carrier





Cheers,

- Alf
 
Reply With Quote
 
Bo Persson
Guest
Posts: n/a
 
      02-14-2010
Robert Fendt wrote:
> And thus spake Seebs <(E-Mail Removed)>
> 14 Feb 2010 07:03:57 GMT:
>
>> dereference a null pointer. (For instance, loops which check
>> whether a pointer is null may have the test removed because, if it
>> were null, it would have invoked undefined behavior to dereference
>> it...)

>
> Sorry to interrupt, but since when is checking a pointer value
> for 0 the same as deferencing it? Checking a pointer treats the
> pointer itself as a value, and comparison against 0 is one of
> the few things that are _guaranteed_ to work with a pointer
> value. So if GCC really would remove a check of the form
>
> if(!pointer)
> do_something(*pointer);
>
> or even
>
> if(pointer == 0)
> throw NullPointerException;
>
> then GCC would be very much in violation of the standard. And
> produce absolutely useless code, as well. What's the point of
> having pointers in a language if you wouldn't even be able to
> perform basic operations on them?
>


Yes, but there are cases where the compiler can determine that the
pointer is ALWAYS null or not-null, and remove code that would execute
otherwise. For example:

*pointer = 42;
if(pointer == 0)
throw NullPointerException;

is known never to throw the exception!


Bo Persson




 
Reply With Quote
 
Ersek, Laszlo
Guest
Posts: n/a
 
      02-14-2010
In article <(E-Mail Removed)>, Robert Fendt <(E-Mail Removed)> writes:

> Checking a pointer treats the
> pointer itself as a value, and comparison against 0 is one of
> the few things that are _guaranteed_ to work with a pointer
> value.


No, evaluating an invalid pointer is undefined behavior.

{
void *p;

p = malloc(1);
free(p);
p; /* UB */
!p; /* UB */
0 != p; /* UB */
}

See the C99 Rationale 6.3.2.3 Pointers for an informative (not
normative) description.

I believe that in this paragraph:

----v----
Regardless how an invalid pointer is created, any use of it yields
undefined behavior. Even assignment, comparison with a null pointer
constant, or comparison with itself, might on some systems result in an
exception.
----^----

"any use" denotes "any evaluation", and "assignment" means "assignment
FROM the invalid pointer". I'm fairly sure the following is valid:

{
int *ip;

ip = malloc(sizeof *ip);
free(ip);
sizeof ip;
sizeof *ip;
ip = 0;
ip;
!ip;
0 != ip;
}

Cheers,
lacos
 
Reply With Quote
 
Richard Tobin
Guest
Posts: n/a
 
      02-14-2010
In article <(E-Mail Removed)>,
Malcolm McLean <(E-Mail Removed)> wrote:

>Derefencing a wild pointer may have different effects,
>particularly on a multi-taskign machine where exact pointer vlaues
>vary from runto run.


It's not a general characteristic of multi-tasking systems that
pointer values vary from run to run. Virtual memory has traditionally
been used to give all instances of a program indistinguishable address
spaces, and addresses will usually be the same.

Recently for security reasons some operating systems have started to
deliberately randomise the locations of, for example, shared
libraries, so pointers are now more likely to vary. (Fortunately this
can usually be disabled for debugging.)

-- Richard
--
Please remember to mention me / in tapes you leave behind.
 
Reply With Quote
 
Robert Fendt
Guest
Posts: n/a
 
      02-14-2010
And thus spake "Bo Persson" <(E-Mail Removed)>
Sun, 14 Feb 2010 11:24:48 +0100:

> Yes, but there are cases where the compiler can determine that the
> pointer is ALWAYS null or not-null, and remove code that would execute
> otherwise. For example:
>
> *pointer = 42;
> if(pointer == 0)
> throw NullPointerException;
>
> is known never to throw the exception!


Yes, that's static optimisation. Nothing wrong with that.
However, the posting I was commenting explicitely described
something different:

>> dereference a null pointer. (For instance, loops which check
>> whether a pointer is null may have the test removed because, if it
>> were null, it would have invoked undefined behavior to dereference
>> it...)


This would mean nothing else than the compiler removing
nullpointer checks solely on the grounds that a nullpointer
cannot be de-referenced legally. So the compiler would see a
pointer dereference, and decide "then it can't be null anyway,
since it's used later". And that's just bull, sorry.

Yes, if there's an unconditional pointer dereference and
_afterwards_ a check for null, the compiler could take this as a
hint that said pointer has been checked for null before the first
dereference and thus remove the superfluous check. So if you had
something like this:

MyType& obj = *pointer;
if (!pointer)
threw NullPointerException;

Since the dereference happens _before_ the check, the program
has already entered the domain of undefined behaviour, and the
check is moot (even if one has not 'used' the object reference
in any other way). If the author of the previous posting meant
that, then I agree (though I have doubts whether GCC really
optimises this agressively). But in that case his comment was at
least not very clear.

Regards,
Robert

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Become The master in computer hardware to become successfull shilla Computer Security 1 01-22-2011 06:19 PM
Knowing the implementation, are all undefined behaviours become implementation-defined behaviours? Michael Tsang C++ 32 03-01-2010 09:15 PM
same code, different providers => different behaviours?? Bart ASP .Net 2 03-22-2007 10:25 AM
"Interesting" C behaviours Rennie deGraaf C Programming 6 11-28-2004 09:27 AM



Advertisments