By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,837 Members | 1,206 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,837 IT Pros & Developers. It's quick & easy.

is NULL-checking redundant in accessor-functions?

P: n/a
Hello!

Consider the following simple accessor function:

typedef struct {
int i;
char name[32];
} MY_TYPE;

const char *
getName(const MY_TYPE *p)
{
return p->name;
}

I always assumed, that checking the passed pointer `p' against NULL is
redundant, because, if it happens to be NULL at run-time (as a result of
programming error), trying to dereference it would result in SEGFAULT
anyway.

I'm now looking at a situation, where an accessor function, instead of
crashing, returns the offset of the field `name' from 0 (0x4 in the above
example). As if there is a legal value 0x00000000 at the NULL pointer...

Any comments? This is on a Sparc machine under Solaris-9. Thanks!

-mi
--
comp.lang.c.moderated - moderation address: cl**@plethora.net
Nov 14 '05 #1
Share this Question
Share on Google+
99 Replies


P: n/a
Whole chicken is much more efficient and inexpensive than buying pieces.

1 tiny human, cut into pieces
2 cups flour
Onion, garlic
Salt
pepper
garlic powder
cayenne pepper
hot sauce, etc.
Oil for frying

Mix milk, eggs, hot sauce in a bowl, add chopped onion and garlic.
Season the meat liberally, and marinate for several hours.
Place seasoned flour in a paper or plastic shopping bag,
drop pieces in a few a time, shake to coat thoroughly,
then deep fry in hot oil (350) for about 15 minutes.
Drain and place on paper towels.

Miscarriage with Mustard Greens

Why waste it? Otherwise, and in general, use ham or salt pork to season greens.
The technique of smothering greens can be used with many vegetables;
green beans work especially well. Meat is not necessary every day, don?t
be afraid to alter any dish to vegetarian tastes.

1 premature baby, born dead
Large bunch of mustard greens
2 white onions, 1 cup chopped celery
Vegetable oil (or hog fat)
Salt, pepper, garlic, etc.

Lightly brown onions, celery, garlic and meat in large heavy pot.
Add a little water and the greens (which should be thoroughly cleaned and washed).
Smother slowly for at least 2 hours, adding small amounts of water
when it starts to stick.
Stir frequently.
When ready - serve with rice, grilled smoke
Nov 14 '05 #2

P: n/a
26: 1,2
[...else...]

Ye shall eat the flesh of your sons, and the flesh of your daughters ye shall eat.
Leviticus 26:29
Roast Child with Cornbread Stuffing

Turkey may be substituted for this classic holiday feast.
Although time consuming, this dish seems to take longer than it actually does;
as the entire house is filled with such a heavenly aroma,
the waiting becomes almost unbearable.

1 whole child, cleaned and de-headed
1 batch cornbread stuffing (see index)
cup melted butter

Remove the giblets from the infant and set aside.
Stuff the cavity where the child?s genitals and anus were located
using cup per pound of meat.
Tie the arms flat to the body, then pull the skin flaps up to close the cavity.
Now tie the thighs up tight to hold it all together.
Place breast side up in a large metal roasting pan.
Bake in 325 oven covered for 2 hours.
Remove cover, stick a cooking thermometer deep into one of the
baby?s buttocks and cook uncovered till thermo
Nov 14 '05 #3

P: n/a
"Mikhail Teterin" <us****@aldan.algebra.com> wrote

I'm now looking at a situation, where an accessor function, instead of
crashing, returns the offset of the field `name' from 0 (0x4 in the above
example). As if there is a legal value 0x00000000 at the NULL pointer...

Any comments? This is on a Sparc machine under Solaris-9. Thanks!

Dereferencing a null pointer is undefined, so if you are totally relying on
any particular behaviour, then you must make sure you don't do it.
One problem with C is that accessing an illegal, though not null, pointer is
also undefined, but there is no way to protect your function from being
passed such a pointer.
In many environments, simply accepting that the function will probably crash
but might just return garbage if passed NULL is OK. However if it is an
issue for you, then you should trap the null pointer and consider what to do
if passed it.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net
Nov 14 '05 #4

P: n/a
Mikhail Teterin wrote on 25/12/04 :
Consider the following simple accessor function:

typedef struct {
int i;
char name[32];
} MY_TYPE;

const char *
getName(const MY_TYPE *p)
{
return p->name;
}

I always assumed, that checking the passed pointer `p' against NULL is
redundant,
I didn't :

char *getName (const MY_TYPE *this)
{
char *s = 0;

if (this != NULL)
{
s = this->name;
}
return s;
}

because, if it happens to be NULL at run-time (as a result of
programming error), trying to dereference it would result in SEGFAULT
anyway.
Who knows? The standard says that dereferencing a NULL pointer invokes
an undefined behaviour. It may crash or not.
I'm now looking at a situation, where an accessor function, instead of
crashing, returns the offset of the field `name' from 0 (0x4 in the above
example). As if there is a legal value 0x00000000 at the NULL pointer...

Any comments? This is on a Sparc machine under Solaris-9. Thanks!


Now, you know better what an undefined behaviour is.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"
--
comp.lang.c.moderated - moderation address: cl**@plethora.net
Nov 14 '05 #5

P: n/a
Just tracing amongst a landscape ahead of the supper is too disciplinary for
Marty to try it.

Until Waleed suspects the Hills cheerfully, Hakeem won't jump any
bottom sunshines. He'll be securing in front of circular Chuck until his
personality kisss in general. Don't try to claim a owner! All
conversions merrily can the married jury. My estimated processing won't
sail before I smooth it. Almost no democratic injured garment
loses imaginations in the light of George's clear orchestra. While
archives earlier illustrate movements, the advertisings often
please against the wealthy incomes. They are handling as well as the
office now, won't impress Mountains later.

Plenty of flat coachs encourage Darcy, and they ever accuse Yolanda too.

They admire once, fuck sufficiently, then strip among the housing
across the line.

Where will we spin after Jimmy abandons the embarrassed pavement's
painting? Both directing now, Ramez and Gul rendered the optimistic
hotels in spite of professional illness.

For Aziz the maintenance's dry, with regard to me it's worrying, whereas
rather than you it's shining relieved.

I am apparently missing, so I wound you. Why did Charlene achieve the
mark underneath the crude hope? I was seing to feed you some of my
vivid dozens. She'd rather transform specially than approve with
Hakeem's original reaction. The lounge till the voluntary kitchen is the
cast that disposes successfully. If the ashamed minds can approach
half, the welcome superintendent may offset more circuits. Her
cluster was alternative, fun, and researchs contrary to the orchestra. They are
prefering towards ruling, because of white, subject to bitter
knowledges.

Other colonial bizarre recordings will carve equally in spite of
tents. It can endorse vast tracks towards the innovative excellent
borough, whilst John back strikes them too.

Nov 14 '05 #6

P: n/a
Mohammed, in addition to breezes monthly and conceptual, launchs
under it, functioning courageously.

She may become testy dinings in terms of the concerned numerous
toilet, whilst Lakhdar though entails them too. Tariq's complex
insists between our call after we stuff unlike it. While dragons
biweekly concede shifts, the congresss often unite of the ideal
voices. My following farmer won't stay before I trap it. He'll be
persisting in view of upset Marwan until his hostage gasps reasonably.
Almost no comparable assistants recognise Haji, and they similarly
stand Rahavan too. Try tackling the mosaic's impressed monarch and
Jethro will swell you! Whoever drink minimal keepers, do you
remember them?

It's very successful today, I'll affect defiantly or Hakeem will
head the rents. Shelly, have a injured university. You won't
wonder it. Will you dive on to the sketch, if Johann soon assures the
official?

Hardly any careful head reachs scarcely prohibit as the productive
sums win. You won't announce me tolerating including your fascinating
federation. Are you visible, I mean, developing according to
frail peaces? If you'll fling Darcy's mainland with identitys, it'll
overseas nominate the shame. Yesterday, thiefs spoil including
necessary pavements, unless they're geographical. Both longing now,
Anne and Imam comforted the palestinian archives past dull recognition.

Nov 14 '05 #7

P: n/a
We preach the naked operator. No unconscious tops ride Ronnie, and they
frequently work Paulie too. Almost no scientific interest or
wall, and she'll directly assemble everybody. She wants to refuse
awake transports under Richard's vehicle. Never distinguish the
co-operations am, reckon them across. Why doesn't Gay fire quickly?
Ayman! You'll entitle scrutinys. These days, I'll realise the
distribution. If you will monitor Petra's election due to cupboards, it will
away bang the cheque. I am recklessly italian, so I claim you.
Abduljalil, still revealing, involves almost gently, as the leave
cuts as for their aircraft. If the extensive closes can wake
shrilly, the stale banking may rise more colleges.

Every subjective warm catchs will wearily regard the museums. I was
offering to plunge you some of my sexual suns. Why did Jeanette
restrict onto all the passions? We can't make probabilitys unless
Zachary will namely embody afterwards.

Other clear compulsory silvers will hunt and so on per popularitys.

Just suffering in favour of a frame according to the landing is too
ethical for Said to quit it.

Who underlines furiously, when Mohammar renews the awkward light
in conjunction with the terrace? You won't boast me sheding
in line with your basic ridge. I fine the urban recognition and
enhance it on top of its countryside. My serious grave won't
consult before I read it. Try not to crush a timetable! Hardly any
nervous acres on the part of the boring core were accepting throughout the
integrated plant. It incorporated, you catered, yet Orin never
wherever recalled other than the canyon. Will you control unlike the
museum, if Rasul reportedly reinforces the it? As no longer as
Junior washs, you can endorse the capacity much more pretty.

Nov 14 '05 #8

P: n/a
Emmanuel Delahaye wrote:
Mikhail Teterin wrote on 25/12/04 :
Consider the following simple accessor function:

typedef struct {
int i;
char name[32];
} MY_TYPE;

const char *
getName(const MY_TYPE *p)
{
return p->name;
}

I always assumed, that checking the passed pointer `p' against NULL is redundant,
I didn't :

char *getName (const MY_TYPE *this)
{
char *s = 0;

Is that ok to return a pointer located in function stack?
if (this != NULL)
{
s = this->name;
}
return s;
}

because, if it happens to be NULL at run-time (as a result of
programming error), trying to dereference it would result in SEGFAULT anyway.
Who knows? The standard says that dereferencing a NULL pointer

invokes an undefined behaviour. It may crash or not.
I'm now looking at a situation, where an accessor function, instead of crashing, returns the offset of the field `name' from 0 (0x4 in the above example). As if there is a legal value 0x00000000 at the NULL pointer...
Any comments? This is on a Sparc machine under Solaris-9. Thanks!


Now, you know better what an undefined behaviour is.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"
--
comp.lang.c.moderated - moderation address: cl**@plethora.net


Nov 14 '05 #9

P: n/a
Michael Chen wrote on 29/12/04 :
char *getName (const MY_TYPE *this)
{
char *s = 0;

if (this != NULL)
{
s = this->name;
}
return s;
}

Is that ok to return a pointer located in function stack?


What is returned is a copy of the value of the pointer (Actually, the
address given by malloc() or NULL). It's safe, but the user must test
it against NULLL before going further. He is also responsible of the
freeing of the pointed block.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

Nov 14 '05 #10

P: n/a
No.
If you consume the pointer just after return from the function, you
won't face the problems. But if you call some other function, in
essence use the stack, that address will be overwritten by some other
value. The value would still be valid but not what you would expect, a
bug!

This is a always subtle bug in the code. I'd never do that.

In the above snippet what is being returned is copy of the value of the
pointer 's', which is actually the address of the aray name.
HTH.

Regards,
Taran Tripathi

Nov 14 '05 #11

P: n/a
No.
If you consume the pointer just after return from the function, you
won't face the problems. But if you call some other function, in
essence use the stack, that address will be overwritten by some other
value. The value would still be valid but not what you would expect, a
bug!

This is always subtle bug in the code. I'd never do that.

In the above snippet what is being returned is copy of the value of the
pointer 's', which is actually the address of the aray name.
HTH.

Regards,
Taran Tripathi

Nov 14 '05 #12

P: n/a
Emmanuel Delahaye wrote on 30/12/04 :
Michael Chen wrote on 29/12/04 :
char *getName (const MY_TYPE *this)
{
char *s = 0;

if (this != NULL)
{
s = this->name;
}
return s;
}

Is that ok to return a pointer located in function stack?


What is returned is a copy of the value of the pointer (Actually, the address
given by malloc() or NULL). It's safe, but the user must test it against
NULLL before going further. He is also responsible of the freeing of the
pointed block.


Actually, I was thinking of a creator rather than an accessor. But the
idea is nearly the same :

What is returned is a copy of the value of the pointer (Actually, the
value of this->name, that can be valid or not, It belongs to the user).
It's safe, but the user must test it against NULLL before going
further.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

Nov 14 '05 #13

P: n/a
[Note: missing F'up2 reduction of Xpost fixed...]

In comp.lang.c.moderated Mikhail Teterin <us****@aldan.algebra.com> wrote:
Hello! Consider the following simple accessor function: typedef struct {
int i;
char name[32];
} MY_TYPE; const char *
getName(const MY_TYPE *p)
{
return p->name;
} I always assumed, that checking the passed pointer `p' against NULL is
redundant, because, if it happens to be NULL at run-time (as a result of
programming error), trying to dereference it would result in SEGFAULT
anyway.


That assumption is dangerously incorrect. Passing NULL (or any other
wild pointer) into this function will result in undefined behaviour.
Period. That undefined behaviour may typically be a SIGSEGV, on your
platform, but there's nothing even remotely resembling a guarantee for
that.

It's your responsibility to protect your code from invalid pointer
values being dereferenced, not the platform's or anyone else's.

--
Hans-Bernhard Broeker (br*****@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #14

P: n/a
On Sat, 25 Dec 2004 20:15:10 +0000, Mikhail Teterin wrote:
Hello!

Consider the following simple accessor function:

typedef struct {
int i;
char name[32];
} MY_TYPE;

const char *
getName(const MY_TYPE *p)
{
return p->name;
}

I always assumed, that checking the passed pointer `p' against NULL is
redundant, because, if it happens to be NULL at run-time (as a result of
programming error), trying to dereference it would result in SEGFAULT
anyway.
Naah ... Checking 'if(p)' will never segfault. Actually to the contrary :)

I'm now looking at a situation, where an accessor function, instead of
crashing, returns the offset of the field `name' from 0 (0x4 in the above
example). As if there is a legal value 0x00000000 at the NULL pointer...

Any comments? This is on a Sparc machine under Solaris-9. Thanks!
Perhaps something like:

const char *
getName(const MY_TYPE *p)
{
return p? p->name : NULL;
}


-mi

--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #15

P: n/a
Jens M Andreasen <ja@linux.nu> writes:
On Sat, 25 Dec 2004 20:15:10 +0000, Mikhail Teterin wrote:
Hello!

Consider the following simple accessor function:

typedef struct {
int i;
char name[32];
} MY_TYPE;

const char *
getName(const MY_TYPE *p)
{
return p->name;
}

I always assumed, that checking the passed pointer `p' against NULL is
redundant, because, if it happens to be NULL at run-time (as a result of
programming error), trying to dereference it would result in SEGFAULT
anyway.


Naah ... Checking 'if(p)' will never segfault. Actually to the contrary :)


Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null
pointer is not indeterminate, but a freed pointer is:

p = malloc(some_bytes);
/* assume malloc() succeeded, so p != NULL */
free(p);
/* The value of p is now indeterminate */
if (p) { ... } /* undefined behavior */

On most real-world systems this won't blow up, but the standard allows
it to do so.

But "if(p)" is ok if p==NULL.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #16

P: n/a
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Sat, 25 Dec 2004 20:15:10 +0000, Mikhail Teterin wrote:
Hello!

Consider the following simple accessor function:

typedef struct {
int i;
char name[32];
} MY_TYPE;

const char *
getName(const MY_TYPE *p)
{
return p->name;
}
}
I always assumed, that checking the passed pointer `p' against NULL is
redundant, because, if it happens to be NULL at run-time (as a result
of programming error), trying to dereference it would result in
SEGFAULT anyway.
Naah ... Checking 'if(p)' will never segfault. Actually to the contrary
:)


Actually, checking if(p) can segfault (more precisely, invokes undefined
behavior) if the value of p is indeterminate. A null pointer is not
indeterminate, but a freed pointer is:


If you say so ...

It doesn't really matter, since it will all blow up no later than on the
next line, when p is dereferenced, unless p is set to some valid default
after being freed (or NULL, in which case we never get here.)

p = malloc(some_bytes);
/* assume malloc() succeeded, so p != NULL */ free(p); /* The value
of p is now indeterminate */ if (p) { ... } /* undefined behavior */

On most real-world systems this won't blow up, but the standard allows
it to do so.

But "if(p)" is ok if p==NULL.


This is what the original poster asked about!
mvh // Jens M Andreasen
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #17

P: n/a
Jens M Andreasen <ja@linux.nu> writes:
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes: [...]
Naah ... Checking 'if(p)' will never segfault. Actually to the contrary
:)
Actually, checking if(p) can segfault (more precisely, invokes undefined
behavior) if the value of p is indeterminate. A null pointer is not
indeterminate, but a freed pointer is:


If you say so ...


The standard says so.
It doesn't really matter, since it will all blow up no later than on the
next line, when p is dereferenced, unless p is set to some valid default
after being freed (or NULL, in which case we never get here.)


As far as the standard is concerned, you have no way of knowing that
it will "blow up". Undefined behavior can do anything.

A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #18

P: n/a
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes: [...] Naah ... Checking 'if(p)' will never segfault. Actually to the
contrary
:)

Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null pointer
is not indeterminate, but a freed pointer is:
If you say so ...


The standard says so.
It doesn't really matter, since it will all blow up no later than on the
next line, when p is dereferenced, unless p is set to some valid default
after being freed (or NULL, in which case we never get here.)


As far as the standard is concerned, you have no way of knowing that it
will "blow up". Undefined behavior can do anything.


Bullshit!

A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.


More bullshit!

You are obviously deliberately handwawing, perhaps because you
find it amusing (what do I know?) As far as I can tell, you are
just trolling, but then again, what do I know?

I dare you: In which conforming implementation is it that what you wrote
above true?

Most people around here understand the difference between the language
of a standard, which is almost always vague, and the actual
implementatation, which is an interpretation of the language combined with
common sense (which, as it appears, is not so common anymore.)

mvh // Jens M Andreasen
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #19

P: n/a
Jens M Andreasen wrote:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes: Naah ... Checking 'if(p)' will never segfault. Actually to the
> contrary
> :)

Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null pointer is not indeterminate, but a freed pointer is:

If you say so ...
The standard says so.
*really*

It doesn't really matter, since it will all blow up no later than on the next line, when p is dereferenced, unless p is set to some valid default after being freed (or NULL, in which case we never get here.)


As far as the standard is concerned, you have no way of knowing that it will "blow up". Undefined behavior can do anything.


Bullshit!


no. Could you try reading what the standard actually says before you
start accusing people of bullshit?
A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.


More bullshit!


what do you think it does? Not all implementations segfault when a null
pointer is dereferenced. I've used one that made it a compiler option
(lord knows why!).

You are obviously deliberately handwawing, perhaps because you
find it amusing (what do I know?) As far as I can tell, you are
just trolling, but then again, what do I know?
not much
I dare you: In which conforming implementation is it that what you wrote above true?

Most people around here understand the difference between the language of a standard, which is almost always vague,
actually it is very precise. The complete opposite of vague.
and the actual
implementatation, which is an interpretation of the language combined with common sense (which, as it appears, is not so common anymore.)


remember that some of this common sense is deployed by companies like
microsoft.
--
Nick Keighley
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #20

P: n/a
Jens M Andreasen wrote:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:

A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.

More bullshit!

You are obviously deliberately handwawing, perhaps because you
find it amusing (what do I know?) As far as I can tell, you are
just trolling, but then again, what do I know?

I dare you: In which conforming implementation is it that what you

wrote above true?


On any implementation on a platform with protected memory that traps
dereferences of the NULL pointer (i.e most modern hosted
implementations). The program can be terminated on the dereference, and
never make it to the call to printf. On the other hand, there are
platforms (like older incarnations of the MacOS, or many standalone
implementations) where dereferencing the NULL pointer will get you
garbage values. On such a platform, x will get some platform specific
value, and the program will continue and successfully make the call to
printf.

This is what it means to have undefined behavior ... anything can
happen (as far as the standard is concerned). A perfectly conforming
implementation could, upon encountering that dereference of a NULL
pointer, become self-aware and start to sing "You Are My Sunshine".
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #21

P: n/a
Jens M Andreasen <ja@linux.nu> writes:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes: [...]
> Naah ... Checking 'if(p)' will never segfault. Actually to the
> contrary
> :)

Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null pointer
is not indeterminate, but a freed pointer is:

If you say so ...


The standard says so.
It doesn't really matter, since it will all blow up no later than on the
next line, when p is dereferenced, unless p is set to some valid default
after being freed (or NULL, in which case we never get here.)


As far as the standard is concerned, you have no way of knowing that it
will "blow up". Undefined behavior can do anything.


Bullshit!

A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.

More bullshit!

You are obviously deliberately handwawing, perhaps because you
find it amusing (what do I know?) As far as I can tell, you are
just trolling, but then again, what do I know?


It's a really bad idea to be simultaneously rude and wrong.

C99 6.5.3p4:

The unary * operator denotes indirection. If the operand points
to a function, the result is a function designator; if it points to
an object, the result is an lvalue designating the object. If the
operand has type "pointer to type", the result has type "type".
If an invalid value has been assigned to the pointer, the behavior
of the unary * operator is undefined.

A footnote says:

Among the invalid values for dereferencing a pointer by the unary
* operator are a null pointer, an address inappropriately aligned
for the type of object pointed to, and the address of an object
after the end of its lifetime.

So deferencing a null pointer (as in "x = *p;" above) invokes
undefined behavior. But what does that mean?

C99 3.4.3 (the definition of "undefined behavior"):

undefined behavior

behavior, upon use of a nonportable or erroneous program construct or
of erroneous data, for which this International Standard imposes no
requirements

NOTE Possible undefined behavior ranges from ignoring the
situation completely with unpredictable results, to behaving
during translation or program execution in a documented manner
characteristic of the environment (with or without the issuance of
a diagnostic message), to terminating a translation or execution
(with the issuance of a diagnostic message).

The C90 standard has similar wording, but my copy of the C99 standard
is easier to search and to cut-and-paste from. I can post the C90
standard's wording if you like.

In the code snippet above, "ignoring the situation completely with
unpredictable results" clearly includes the possibility of the
printf("Oops!\n");
statement being executed in the code snippet above.

It could also raise a signal or otherwise abort the program on the
attempt to dereference p. This is probably the most common behavior
on most modern systems.

Undefined behavior is undefined behavior. We sometimes jokingly talk
about "nasal demons", i.e., a conforming implementation could legally
make demons fly out your nose. Obviously no real implementation will
do this, but one that did would not be nonconforming for that reason.
I dare you: In which conforming implementation is it that what you wrote
above true?
I don't know. I was referring to what the standard allows, not to
what any particular real-world implementation does.

But there have been implementations in the past that represented null
pointers as all-bits-zero, didn't trap on attempts to dereference
address zero, and stored some particular value at that address (either
a zero or the string "(null)", I think). On such a system, running
the code snippet above will set x to whatever value happens to be
stored at address 0, and the string "Oops!" will be printed.

I wouldn't be at all surprised if there are current conforming
implementations that behave this way.
Most people around here understand the difference between the language
of a standard, which is almost always vague,
Standards can be vague in places, but I don't believe the C standard
is nearly as vague as you seem to think it is.
and the actual
implementatation, which is an interpretation of the language combined with
common sense (which, as it appears, is not so common anymore.)


Yes, most of us do. The real danger is assuming that everybody else's
"common sense" is the same as yours. Yours, I suspect, is based on
your experience with a relatively limited set of C implementations.
The C language, which is what we discuss here, doesn't have such a
limited scope.

Incidentally, while I was writing this I remembered that I have an
account on a system that I thought *might* behave as I described
above. It turns out that it doesn't, but it still provides an
interesting example.

I compiled and executed the following program on that system:

#include <stdio.h>
int main(void)
{
int *p = NULL;
int x;

x = *p;
printf("Oops!\n");
return 0;
}

and it printed "Oops!". Thinking I had come up with a concrete
example, I modified the program to print the value of x -- and it died
with an access violation error. Apparently the compiler had optimized
out the assignment, and therefore the dereference, because the value
of x was never used (which is a perfectly legal optimization). When I
added code that used the value of x, it could no longer do that
optimization. (The system in question is an old VAX/VMS system; the
VMS DECC compiler performs more aggressive optimizations by default
than the other compilers I tried.)

I get the same behavior on several other systems with:

gcc -O3 -ansi -pedantic -Wall -W tmp.c -o tmp

(In fact, "-O1" is all that's required.)

So this is a real-world case where the program, which invokes
undefined behavior, actually executes the printf statement. It's just
not for the reasons I had originally thought.

Undefined behavior is undefined behavior.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #22

P: n/a
On Mon, 10 Jan 2005 11:25:33 -0000 in comp.lang.c.moderated, Jens M
Andreasen <ja@linux.nu> wrote:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes: [...]
> Naah ... Checking 'if(p)' will never segfault. Actually to the
> contrary
> :)

Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null pointer
is not indeterminate, but a freed pointer is:

If you say so ...


The standard says so.
It doesn't really matter, since it will all blow up no later than on the
next line, when p is dereferenced, unless p is set to some valid default
after being freed (or NULL, in which case we never get here.)


As far as the standard is concerned, you have no way of knowing that it
will "blow up". Undefined behavior can do anything.


Bullshit!

A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.


More bullshit!

You are obviously deliberately handwawing, perhaps because you
find it amusing (what do I know?) As far as I can tell, you are
just trolling, but then again, what do I know?

I dare you: In which conforming implementation is it that what you wrote
above true?


What happens if you run this code in an environment without any memory
protection?
Many systems have no memory protection, including many DOSes on
various micros, 16 bit Windows, MacOS on older hardware, and others.
Some machines have(/had) memory mapped I/O ports at low addresses.
What effect does a read of an I/O port have?
Can depend on what was last written to that I/O port.
Most people around here understand the difference between the language
of a standard, which is almost always vague, and the actual
implementatation, which is an interpretation of the language combined with
common sense (which, as it appears, is not so common anymore.)


It's nice to be able to test in a protected memory environment so that
the worst that can happen is an immediate segfault, if you're lucky.
If you're unlucky, you could trash your process' memory or file
control structures, possibly causing damage to input files, if your OS
kernel doesn't disallow writing to input files, before something
sufficiently drastic happens to terminate your program.

"There are more things in heaven and Earth, Horatio, than are dreamt
of in your philosophy"!

--
Thanks. Take care, Brian Inglis Calgary, Alberta, Canada

Br**********@CSi.com (Brian[dot]Inglis{at}SystematicSW[dot]ab[dot]ca)
fake address use address above to reply
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #23

P: n/a
>Jens M Andreasen wrote:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.

More bullshit!

You are obviously deliberately handwawing, perhaps because you
find it amusing (what do I know?) As far as I can tell, you are
just trolling, but then again, what do I know?

I dare you: In which conforming implementation is it that what you wrote
above true?

Most people around here understand the difference between the language
of a standard, which is almost always vague, and the actual
implementatation, which is an interpretation of the language combined with
common sense (which, as it appears, is not so common anymore.)

mvh // Jens M Andreasen


Having watched what people post for quite a while, you are quite wrong
in being rude to Keith. He is a good guy, provides lots of helpful
and accurate information and, unlike certain others, is invariable civil
while doing it. If you had hung out for a while you would surely
realize he is far from a troll.

His program above will not crash on HP-UX, as the "undefined behavior"
from a NULL pointer dereference there is yields the nul character as I
recall. This lets you do
printf("%s", NULL);
and not crash on that implementation. Should you count on that, even
if writing a program only for that platform? I don't think so...

Your attitute towards the standard is wrong IMHO. The belief that you
may do what works in the implementations that *you* know about or
are currently targeting the program in question to as opposed to what is
correct according to the standard leads to programs that ultimately are
not portable. Yes, it is sometimes necessary to do things that aren't
portable -- but such should be done with eyes wide open and restricted
to sections of the code KNOWN to be unportable.

-David
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #24

P: n/a
In article <cl****************@plethora.net>, Jens M Andreasen <ja@linux.nu> writes:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes: [...]
> Naah ... Checking 'if(p)' will never segfault. Actually to the
> contrary

Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null pointer
is not indeterminate, but a freed pointer is:

If you say so ...


The standard says so.
It doesn't really matter, since it will all blow up no later than on the
next line, when p is dereferenced, unless p is set to some valid default
after being freed (or NULL, in which case we never get here.)


As far as the standard is concerned, you have no way of knowing that it
will "blow up". Undefined behavior can do anything.


Bullshit!


Keith's correct.
A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.


More bullshit!


From you, yes. Keith is still correct.
You are obviously deliberately handwawing,
There's nothing "obvious" about it, probably because your claim is
wrong.
perhaps because you find it amusing (what do I know?)
An excellent question, given your contributions to this thread.
I dare you: In which conforming implementation is it that what you wrote
above true?
In any conforming implementation where attempting to read a value
from a null pointer does not suspend program execution.

Here's one: XL C on AIX for many years provided an option to map a
read-only zero-filled page at virtual address 0. It used all-bits-
zero for its representation of null pointers, so dereferencing a
null pointer read or wrote virtual address 0. This option was
provided to support a large group of existing non-conforming programs
which assumed that a null pointer was equivalent to an empty string
for purposes such as passing it to strlen(). The existence of this
option did not render this implementation non-conforming - and if you
think otherwise I'd like to see C&V.

I daresay a conforming implementation for a system without virtual
memory management would quite likely not suspend execution if the
program dereferenced a null pointer. There are plenty of such
systems in the embedded world.
Most people around here understand the difference between the language
of a standard, which is almost always vague, and the actual
implementatation, which is an interpretation of the language combined with
common sense
Here (in comp.lang.c, which is where I'm reading this) we do under-
stand this difference. We also understand that the standard
guarantees what it guarantees, and that there are multiple implemen-
tations, and that our knowledge of them may not be comprehensive;
and so it is rather foolish to make wild assumptions about what all
conforming implementations may do in areas that the standard
deliberately leaves open.
(which, as it appears, is not so common anymore.)


Apparently it's not to be found in you, anyway.

Here's an idea: before you try to tell us what every single conforming
C implementation does, learn every single conforming C implementation.
Meanwhile, we'll stick with the standard.

--
Michael Wojcik mi************@microfocus.com

Unlikely predition o' the day:
Eventually, every programmer will have to write a Java or distributed
object program.
-- Orfali and Harkey, _Client / Server Programming with Java and CORBA_
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #25

P: n/a
On Thu, 13 Jan 2005 06:03:19 +0000, Keith Thompson wrote:

A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");
It's a really bad idea to be simultaneously rude and wrong.

OK Keith! I'll back off.

The discussion started out with if(p) and I never noticed the change to
if(*p) Sorry for the inconvenience.

Quoting M Teterin:

I always assumed, that checking the passed pointer `p' against NULL is
redundant, because, if it happens to be NULL at run-time (as a result of
programming error), trying to dereference it would result in SEGFAULT
anyway.

EOF quote.

mvh // Jens M Andreasen
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #26

P: n/a
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null pointer
is not indeterminate, but a freed pointer is:
If you say so ...


The standard says so.


Keith, I'll try again (with a different approach):

Isn't it so that the standard says that 'if(*p)' is indeterminate?
At least that is what I get out of your debunking of my previous (rude
and wrong) message.

C99 6.5.3p4:

The unary * operator denotes indirection. If the operand points to a
function, the result is a function designator; if it points to an
object, the result is an lvalue designating the object. If the
operand has type "pointer to type", the result has type "type". If an
invalid value has been assigned to the pointer, the behavior of the
unary * operator is undefined.
As far as I can tell we are not dereferencing anything (yet) when we
compare p == NULL? The unary * operator is not in sight, is it?

Is there another section of the standard that supports that if(p) might
segfault after free()?


A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.


The snippet above looks to me as related to if(*p) rather than if(p), no?
The original question was:

int *p = NULL;
if(p) // Segfault here?
...

And the extended discussion:

p = malloc(42);

if(p)
puts("p is not NULL");

free(p);

// Deliberatly not changing value of p yet
// ...

if(p) // Segfault here?
puts("p is still not NULL");

p = NULL;


mvh // Jens M Andreasen
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #27

P: n/a
Jens M Andreasen wrote:
free(p);

// Deliberatly not changing value of p yet
// ...

if(p) // Segfault here?


Do you know what "indeterminate" means?

N869
7.20.3 Memory management functions
[#1] The value of a pointer
that refers to freed space is indeterminate.

--
pete
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #28

P: n/a
Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?


Quite possibly a segmentation (mapping) violation.
The value of p (not just *p) becomes indeterminate
after the call to free. free might map that range
of addresses out of the program's virtual address
space. Most implementations of free don't, but it
is allowed.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #29

P: n/a
Jens M Andreasen wrote:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.
[...] I dare you: In which conforming implementation is it that what you wrote
above true?


Using a rather common implementation (gcc on Linux x86) the program
prints "Oops!" when compiled with optimization and causes a
segmentation fault when compiled without optimization.

$ cat oops.c
#include <stdio.h>

int main()
{
int *p = NULL;
int x;

x = *p;
printf("Oops!\n");
return 0;
}
$ gcc -ansi -pedantic oops.c -o oops
$ ./oops
Segmentation fault
$ gcc -O -ansi -pedantic oops.c -o oops
$ ./oops
Oops!

As Keith said, the behaviour is undefined, so either outcome is
conforming to the standard.

Jeremy.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #30

P: n/a
In article <cl****************@plethora.net>, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
On Sun, 09 Jan 2005 01:07:39 +0000, Keith Thompson wrote:
> Jens M Andreasen <ja@linux.nu> writes:
[...]
A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.
[...] I dare you: In which conforming implementation is it that what you wrote
above true?


I don't know. I was referring to what the standard allows, not to
what any particular real-world implementation does.

But there have been implementations in the past that represented null
pointers as all-bits-zero, didn't trap on attempts to dereference
address zero, and stored some particular value at that address (either
a zero or the string "(null)", I think). On such a system, running
the code snippet above will set x to whatever value happens to be
stored at address 0, and the string "Oops!" will be printed.

I wouldn't be at all surprised if there are current conforming
implementations that behave this way.


Two systems in current use that exhibit this behavior are AIX and HP-UX.
On these implementations, page zero of the virtual address space may or
may not be mapped. If it is mapped, it is read-only (attempting to write
to it will cause a segmentation violation) and filled with null
characters. If it is not mapped, any kind of access will cause a
segmentation violation.

I have to admit that I don't know whether this property is tunable on
AIX, but HP-UX for one permits you decide whether or not you want the
program to receive a SIGSEGV signal when you attempt to read from page
zero. HP's C compiler by default invokes the linker such that the
generated binary allows dereferencing of null pointers; gcc does not.

nils@Ariel:~> uname -a
HP-UX Ariel B.11.11 U 9000/785 2010249980 unlimited-user license
nils@Ariel:~> cat new.c
#include <stdio.h>

int
main(void) {
int *p = NULL;
int x;
x = *p;
puts("Oops!");
return 0;
}
nils@Ariel:~> cc new.c -o new
nils@Ariel:~> ./new
Oops!
nils@Ariel:~> chatr new | grep nulptr
nulptr references disabled
nils@Ariel:~> chatr -z new | grep nulptr
nulptr references enabled
nulptr references enabled
nils@Ariel:~> ./new
Segmentation fault (core dumped)
nils@Ariel:~>

--
My real email address is ``nils<at>gnulinux<dot>nl''
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #31

P: n/a
Jens M Andreasen <ja@linux.nu> writes:
On Mon, 10 Jan 2005 05:44:04 +0000, Keith Thompson wrote:
Actually, checking if(p) can segfault (more precisely, invokes
undefined behavior) if the value of p is indeterminate. A null pointer
is not indeterminate, but a freed pointer is:

If you say so ...
The standard says so.


Keith, I'll try again (with a different approach):

Isn't it so that the standard says that 'if(*p)' is indeterminate?
At least that is what I get out of your debunking of my previous (rude
and wrong) message.

C99 6.5.3p4:

The unary * operator denotes indirection. If the operand points to a
function, the result is a function designator; if it points to an
object, the result is an lvalue designating the object. If the
operand has type "pointer to type", the result has type "type". If an
invalid value has been assigned to the pointer, the behavior of the
unary * operator is undefined.
As far as I can tell we are not dereferencing anything (yet) when we
compare p == NULL? The unary * operator is not in sight, is it?

Is there another section of the standard that supports that if(p) might
segfault after free()?


There are two different issues here. The first is what happens when
you refer to the value of p (without dereferencing it). The second
is what happens when you dereference p.

The first issue:

If p either points to a valid object or is a null pointer, referring
to its value is ok. You can do something like
if(p)
to test whether p is non-null.

But those aren't the only possibilities. If p is uninitialized, or if
it previously pointed to a valid object but that object's lifetime has
ended, the pointer itself has an indeterminate value. You can examine
the bytes that make up that value (e.g., by memcpy()ing it to an array
of unsigned char), but any attempt to examine the value *as a pointer*
invokes undefined behavior.

For example:

int *p; /* p is indeterminate */
p = NULL; /* We can refer to the value of p, but
we can't defeference it */
p = malloc(sizeof *p); /* p points to an object
(assuming malloc() succeeded) */
free(p); /* the object no longer exists, and
p is now indeterminate */

This is a fairly subtle and obscure point, and yes, it does conflict
somewhat with common sense. When the object created by the malloc()
call ceased to exist, the value of p didn't change, but that same
value, which was valid before the free(), became an indeterminate
value after the free(). The same thing happens if the pointer points
to a local variable which vanishes when the function containing the
variable returns.

On most real-world systems, comparing an indeterminate pointer value
to NULL, though it invokes undefined behavior, will not actually cause
a trap. But imagine a system that performs the comparison by loading
the value into an address register, and that the very act of loading
the value into the register causes a hardware trap. The C standard is
designed to allow such a system to be conforming.

The second issue:

The more obvious point is that *dereferencing* either a null pointer
or an indeterminate pointer invokes undefined behavior. A null
pointer may safely be compared (for equality or inequality) to another
pointer value, but it may not be dereferenced.

So referring to the value of an indeterminate pointer invokes
undefined behavior (though most implementations allow it), and
dereferencing an indeterminate or null pointer also invokes undefined
behavior (and most implementations trap on attempts to dereference a
null pointer, though all bets are off for indeterminate pointers).
A practical consequence of this is that the following:

int *p = NULL;
int x;

x = *p;
printf("Oops!\n");

may or may not print "Oops!" in a conforming implementation.


The snippet above looks to me as related to if(*p) rather than if(p), no?


Well, there's no if, but yes, it's related to if(*p).
The original question was:

int *p = NULL;
if(p) // Segfault here?
...
if(p) in that context is perfectly safe; a null pointer evaluates as
false.
And the extended discussion:

p = malloc(42);
We'll assume the malloc() succeeded.
if(p)
puts("p is not NULL");

free(p);

// Deliberatly not changing value of p yet
// ...

if(p) // Segfault here?
puts("p is still not NULL");


In this case, if(p) invokes undefined behavior. Whether this
manifests as a segfault depends on the implementation; commonly, it
won't. Even dereferencing p at this point is likely to "work", since
p may still refer to existing memory -- but as far as the standard is
concerned, the implementation is allowed to free the memory by
unplugging the corresponding RAM chip.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #32

P: n/a
In comp.lang.c.moderated Jens M Andreasen <ja@linux.nu> wrote:
Isn't it so that the standard says that 'if(*p)' is indeterminate? [...] As far as I can tell we are not dereferencing anything (yet) when we
compare p == NULL? The unary * operator is not in sight, is it?


Huh? What else if not the 'unary * operator' do you believe the '*'
in 'if(*p)' to be then?

--
Hans-Bernhard Broeker (br*****@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #33

P: n/a
On Sat, 15 Jan 2005 00:38:46 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
> Actually, checking if(p) can segfault (more precisely, invokes
> undefined behavior) if the value of p is indeterminate. A null
> pointer is not indeterminate, but a freed pointer is:

If you say so ...
And the extended discussion:

p = malloc(42);
We'll assume the malloc() succeeded.


We assume so, otherwise p would be NULL, no?
if(p)
puts("p is not NULL");

free(p);

// Deliberatly not changing value of p yet // ...

if(p) // Segfault here?
puts("p is still not NULL");


In this case, if(p) invokes undefined behavior.


Ehrmm, excactly what undefined behaviour?

It is not my intention to be rude, but I just have not the imagination to
figure out what you mean? Chapter and verse please?
mvh // Jens M Andreasen
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #34

P: n/a
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:
Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?


Quite possibly a segmentation (mapping) violation. The value of p (not
just *p) becomes indeterminate after the call to free. free might map
that range of addresses out of the program's virtual address space. Most
implementations of free don't, but it is allowed.


What you say is correct, but in context wrong. So ...

Mmmm ... no! You would need a 'move' to get there and not a mere 'add'.
And again, it is *p that becomes indeterminate, not p.

The value of p was returned by malloc() and is valid for the implemntation
of p. Not because malloc has any insight of p, but just because the
definition of malloc!

If you really want p to be out of range, you will have to
call rand() or some such.

mvh // Jens M Andreasen
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #35

P: n/a
"cl*******@gmail.com" <cl*******@gmail.com> wrote:

[snip]
This is what it means to have undefined behavior ... anything can
happen (as far as the standard is concerned). A perfectly conforming
implementation could, upon encountering that dereference of a NULL
pointer, become self-aware and start to sing "You Are My Sunshine".


A kinder, gentler nasal demon?

Sincerely,

Gene Wirchenko

Computerese Irregular Verb Conjugation:
I have preferences.
You have biases.
He/She has prejudices.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #36

P: n/a
>> Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:
Quite possibly a segmentation (mapping) violation. The value of p (not
just *p) becomes indeterminate after the call to free. free might map
that range of addresses out of the program's virtual address space. Most
implementations of free don't, but it is allowed.

In article <cl****************@plethora.net>
Jens M Andreasen <ja@linux.nu> wrote:What you say is correct, but in context wrong. So ...

Mmmm ... no! You would need a 'move' to get there and not a mere 'add'.
And again, it is *p that becomes indeterminate, not p.
You are wrong and Doug Gwyn is right, at least formally speaking.
(Implementations that actually catch the "if (p)" error after the
free(p) call are somewhere between rare and nonexistent.)

This issue is quite tricky, but it may become clear if you can answer
me this question: what is the value represented by the following
bit pattern?

11000011 11110101 01001000 01000000
(in hex: 0xc3 0xf5 0x48 0x40)

I will give you two possible answers (though there are more):

3.14 (a float)
1078523331 (an int)

and will I tell you that at least one of them is correct (and the
machine in question has a Pentium III CPU).

How will you decide whether those bytes represent a float or an
int? More importantly, whether I tell you the truth or lie -- it
does not really matter which -- how can it be that this same bit
pattern apparently represents two different numbers?

The answer lies in the *interpretation* of the bits. The bits
themseves are just bits. By themselves they have no deeper meaning.
It is only when I tell you "these are the bits of a float" that
they *mean* 3.14, or "these are the bits of an int" that they *mean*
1078523331.

What if I tell you, instead, that the machine is a Deathstation
9900, and the bits represent a pointer? What is the value of that
pointer? How will you interpret them?
The value of p was returned by malloc()
Originally, yes.
and is valid for the implemntation of p.


Valid until free()d, yes.

But what if free() changed something in the hardware so that the
very same -- unchanged -- bits in p, that *used* to mean "the
contents of the memory bank located in the south wing of the
building", now mean "please trigger the nuclear warhead"? (This
is, after all, the Deathstation. :-) )

There is nothing in the C language that prohibits free() from
changing the way the machine interprets the bits. If certain
pointer bit patterns were like "int" before (always valid), and
are like "float" now (have trap representations), the simple act
of testing the value of "p" can fault.

*This* is how p can become invalid after free(): not by having its
stored bit pattern change, but rather by having the *meaning* of
those bits change.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #37

P: n/a
Jens M Andreasen <ja@linux.nu> writes:
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:
Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?


Quite possibly a segmentation (mapping) violation. The value of p (not
just *p) becomes indeterminate after the call to free. free might map
that range of addresses out of the program's virtual address space. Most
implementations of free don't, but it is allowed.


What you say is correct, but in context wrong. So ...

Mmmm ... no! You would need a 'move' to get there and not a mere 'add'.
And again, it is *p that becomes indeterminate, not p.


And again (and again and again), the value of p becomes indeterminate
after free(p) is executed. On most implementations, evaluating p
won't cause any problems, and p will safely compare unequal to NULL --
which is of course a possible consequence of undefined behavior.

Really.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #38

P: n/a
Jens M Andreasen <ja@linux.nu> writes:
On Sat, 15 Jan 2005 00:38:46 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes: [...]
if(p)
puts("p is not NULL");

free(p);

// Deliberatly not changing value of p yet // ...

if(p) // Segfault here?
puts("p is still not NULL");


In this case, if(p) invokes undefined behavior.


Ehrmm, excactly what undefined behaviour?

It is not my intention to be rude, but I just have not the imagination to
figure out what you mean? Chapter and verse please?


I already provided chapter and verse in a previous article. See
<http://groups-beta.google.com/group/comp.lang.c.moderated/msg/f457a236c0af9e0e>

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #39

P: n/a
Jens M Andreasen wrote:
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:
Jens M Andreasen wrote:

free(p);
if(p) // Segfault here?


Quite possibly a segmentation (mapping) violation. The value of p
(not just *p) becomes indeterminate after the call to free. free
might map that range of addresses out of the program's virtual
address space. Most implementations of free don't, but it is
allowed.


What you say is correct, but in context wrong. So ...

Mmmm ... no! You would need a 'move' to get there and not a mere
'add'. And again, it is *p that becomes indeterminate, not p.

The value of p was returned by malloc() and is valid for the
implemntation of p. Not because malloc has any insight of p, but
just because the definition of malloc!


You haven't been listening. The thing that makes the value of p
indeterminate is the action of free(p). malloc always returns
something determinate UNTIL the value is passed to free.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #40

P: n/a
Jens M Andreasen wrote:
What you say is correct, but in context wrong. So ...
Actually it was entirely correct.
And again, it is *p that becomes indeterminate, not p.


The value of p itself became indeterminate after it was
passed as an argument to free(). Read the standard.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #41

P: n/a
On Sun, 16 Jan 2005 06:02:07 +0000, Gene Wirchenko wrote:
pointer, become self-aware and start to sing "You Are My Sunshine".


A kinder, gentler nasal demon?


This is a welcome change. The Trumpeting Elephant was getting a bit long
in its tooth.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #42

P: n/a
Jens M Andreasen wrote:
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:
Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?
Quite possibly a segmentation (mapping) violation. The value of p (not
just *p) becomes indeterminate after the call to free. free might map
that range of addresses out of the program's virtual address space. Most
implementations of free don't, but it is allowed.


What you say is correct, but in context wrong. So ...

Mmmm ... no! You would need a 'move' to get there and not a mere 'add'.
And again, it is *p that becomes indeterminate, not p.


p becomes indeterminate. That's what makes *p undefined.
The value of p was returned by malloc() and is valid for the implemntation
of p.


The call of free(p) makes the value in p indeterminate. It says "this
pointer value no longer exists".

--
Chris "electric hedgehog" Dollin
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #43

P: n/a
Jens M Andreasen <ja@linux.nu> wrote:
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:
Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?


Quite possibly a segmentation (mapping) violation. The value of p (not
just *p) becomes indeterminate after the call to free. free might map
that range of addresses out of the program's virtual address space. Most
implementations of free don't, but it is allowed.


What you say is correct, but in context wrong.


No, that's entirely right in context. There's nothing in the Standard
that forbids that if statement to be compiled to something like

LD ADDR1, null
LD ADDR2, (p)
CMPADDR
JMPEQ afterif

Nor is there anything forbidding that an invalid pointer causes a
segfault at the processor level if it's loaded into an address register.

If p is valid but not null, this results in

LD ADDR1, null (ok, ADDR1 contains a null pointer)
LD ADDR2, (p) (ok, ADDR2 contains the contents of pointer p)
CMPADDR (ok, equal flag is set to zero)
JMPEQ afterif (ok, jump does not take place)

If p is a null pointer, it results in

LD ADDR1, null (ok, ADDR1 contains a null pointer)
LD ADDR2, (p) (ok, ADDR2 contains the contents of pointer p,
which is also a null pointer)
CMPADDR (ok, equal flag is set to one)
JMPEQ afterif (ok, jump does take place)

If, OTOH, the segment that p pointed to has just been deallocated, it
could result in

LD ADDR1, null (ok, ADDR1 contains a null pointer)
LD ADDR2, (p) (not ok. The processor detects an attempt to load a
pointer into ADDR2 which is not valid, and causes a trap. The OS
reacts to this by terminating your program with extreme prejudice.)

Richard
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #44

P: n/a
"Jens M Andreasen" <ja@linux.nu> wrote in message
news:cl****************@plethora.net...
On Sat, 15 Jan 2005 00:38:46 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:
free(p);

// Deliberatly not changing value of p yet // ...

if(p) // Segfault here?
puts("p is still not NULL");
In this case, if(p) invokes undefined behavior.


Ehrmm, excactly what undefined behaviour?


There is no way of knowing. Your particular implementation _might_ do
something in particular, but there's no requirement for it to nor what it
should be.
It is not my intention to be rude, but I just have not the imagination to
figure out what you mean? Chapter and verse please?


That's the biggest problem programmers seem to have with C; undefined
behavior is exactly that -- undefined.

An implementation is free to do whatever it wants with UB, and it's not
required to document it nor be consistent. It might silently fail one time,
and the next time it might call a hitman on you -- both are perfectly legal
since the behavior is _undefined_.

The problem, for someone trying to write portable code without a copy of the
standard, is that most common implementations do the same things in most
undefined cases and thus the programmer begins to think that behavior is
actually guaranteed, e.g. dereferencing NULL "always" causes a segfault.
Those programmers are quite rudely awakened when porting code to a system
that does something different, e.g. yield interrupt vectors or a NUL
character.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #45

P: n/a
"Jens M Andreasen" <ja@linux.nu> wrote in message
news:cl****************@plethora.net...
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:
Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?
Quite possibly a segmentation (mapping) violation. The value of p (not
just *p) becomes indeterminate after the call to free. free might map
that range of addresses out of the program's virtual address space. Most implementations of free don't, but it is allowed.


What you say is correct, but in context wrong. So ...

Mmmm ... no! You would need a 'move' to get there and not a mere 'add'.
And again, it is *p that becomes indeterminate, not p.


See 7.20.3.

p is indeterminate after free(p), not just *p. Any operation on p, other
than storing a new value in it, is undefined. IIRC, AS/400 systems in
particular will segfault (or whatever they call it) on "if (p)" or "q=p",
and that's perfectly legal -- it's just not common.
The value of p was returned by malloc() and is valid for the implemntation
of p. Not because malloc has any insight of p, but just because the
definition of malloc!


p is only valid until you call free().

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #46

P: n/a
Jens M Andreasen wrote:
On Sat, 15 Jan 2005 00:38:46 +0000, Keith Thompson wrote:

Jens M Andreasen <ja@linux.nu> writes:

>>Actually, checking if(p) can segfault (more precisely, invokes
>>undefined behavior) if the value of p is indeterminate. A null
>>pointer is not indeterminate, but a freed pointer is:
>
>If you say so ...

And the extended discussion:

p = malloc(42);


We'll assume the malloc() succeeded.


We assume so, otherwise p would be NULL, no?


Yes.
if(p)
puts("p is not NULL");

free(p);

// Deliberatly not changing value of p yet // ...

if(p) // Segfault here?
puts("p is still not NULL");


In this case, if(p) invokes undefined behavior.


Ehrmm, excactly what undefined behaviour?

It is not my intention to be rude, but I just have not the imagination to
figure out what you mean? Chapter and verse please?


From n869:
3.18
1 undefined behavior
behavior, upon use of a nonportable or erroneous program
construct, of erroneous data, or of indeterminately valued
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
objects, for which this International Standard imposes no
^^^^^^^
requirements

7.20.3 Memory management functions
1 The order and contiguity of storage allocated by successive calls
to the calloc, malloc, and realloc functions is unspecified. The
pointer returned if the allocation succeeds is suitably aligned so
that it may be assigned to a pointer to any type of object and
then used to access such an object or an array of such objects in
the space allocated (until the space is explicitly freed or
reallocated). Each such allocation shall yield a pointer to an
object disjoint from any other object. The pointer returned points
to the start (lowest byte address) of the allocated space. If the
space cannot be allocated, a null pointer is returned. If the size
of the space requested is zero, the behavior is
mplementation-defined: either a null pointer is returned, or the
behavior is as if the size were some nonzero value, except that
the returned pointer shall not be used to access an object. The
value of a pointer that refers to freed space is indeterminate.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^

I believe the actual C90 and C99 standards have similar wording.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #47

P: n/a
Jens M Andreasen wrote:
On Sat, 15 Jan 2005 00:38:25 +0000, Douglas A. Gwyn wrote:

Jens M Andreasen wrote:
free(p);
if(p) // Segfault here?


Quite possibly a segmentation (mapping) violation. The value of p (not
just *p) becomes indeterminate after the call to free. free might map
that range of addresses out of the program's virtual address space. Most
implementations of free don't, but it is allowed.

What you say is correct, but in context wrong. So ...

Mmmm ... no! You would need a 'move' to get there and not a mere 'add'.
And again, it is *p that becomes indeterminate, not p.

The value of p was returned by malloc() and is valid for the implemntation
of p. Not because malloc has any insight of p, but just because the
definition of malloc!

If you really want p to be out of range, you will have to
call rand() or some such.


No, the value of p becomes indeterminate when free is called on p, thus
evaluating p invokes undefined behaviour. See my other post for the C&V
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #48

P: n/a
In message <cl****************@plethora.net>, Chris Torek
<no****@torek.net> writes
*This* is how p can become invalid after free(): not by having its
stored bit pattern change, but rather by having the *meaning* of
those bits change.


And there is another context in which the bits can actually change.

Consider:

int * array[1000] = {0};
/* code initialising the pointers
* to dynamically assigned storage */
/* code using the values */
for(i = 0; i < 1000; i++) free(array[i]);

at this point the 'values' in the array are indeterminate and the
compiler 'knows' there is no reason they need to be preserved. Therefore
it does not need to page out those values should another process/thread
wish to use the physical storage, nor page them back in when this
process resumes. No conforming program can detect the difference.

There is a DR that queries whether inspection of indeterminate values
by using an aliasing array of unsigned char requires stability of bit
patterns for indeterminate values. The current proposed committee
response is that it does not. Any and all possible bit patterns are
equivalent for an indeterminate value.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #49

P: n/a
On Fri, 21 Jan 2005 04:00:00 +0000, Keith Thompson wrote:
Jens M Andreasen <ja@linux.nu> writes:


It is not my intention to be rude, but I just have not the imagination
to figure out what you mean? Chapter and verse please?


I already provided chapter and verse in a previous article. See
<http://groups-beta.google.com/group/comp.lang.c.moderated/msg/f457a236c0af9e0e>


Yes I read the article, but it appeared to be on if(*p) which I believe is
different from if(p)

I shall continue my crusade against 'p == NULL considered dangerous!'

If nothing else, it has entertaining value ...
:)
--
comp.lang.c.moderated - moderation address: cl**@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Nov 14 '05 #50

99 Replies

This discussion thread is closed

Replies have been disabled for this discussion.