about NULL as a parameter to a libc function

B

Ben Pfaff

James Kuyper said:
Perhaps, though I doubt that the fact that __NULL__ is a reserved word
gives an implementation permission to ignore the standard semantics of
'&', which can never appear as the first token of an expression with
integer type.

Did you mean to add more qualifiers? I believe that &x - &x is
an expression with integer type, for appropriately defined 'x'.
 
J

James Kuyper

Did you mean to add more qualifiers? I believe that &x - &x is
an expression with integer type, for appropriately defined 'x'.

You've got a point there. I stated my point too generally, and I'm not
sure how to reword it to cover such issues. I'll concede that &__NULL__
could have integer type if __NULL__ were a macro whose expansion had a
form like that. But that's not the meaning for __NULL__ that was suggested.
 
I

Ike Naar

Sorry for my previous post which did not contain any new text.
Something went wrong during posting.

In the meantime, James has already submitted a response
similar to what I was trying to submit:
Kaz's quoted statement about "contant integral expression" contradicts
6.6 p6 which states that an integer constant expression shall have
integer type, while &__NULL__ has type pointer-to-char.
 
K

Kaz Kylheku

Perhaps, though I doubt that the fact that __NULL__ is a reserved word
gives an implementation permission to ignore the standard semantics of

__NULL__ being a reserved word means that demons can fly out of the
programmer's nose when it is used.
 
K

Kaz Kylheku

Sorry for my previous post which did not contain any new text.
Something went wrong during posting.

In the meantime, James has already submitted a response
similar to what I was trying to submit:
Kaz's quoted statement about "contant integral expression" contradicts
6.6 p6 which states that an integer constant expression shall have
integer type, while &__NULL__ has type pointer-to-char.

On a DeathStation 9000, &__NULL__ overwrites the partition table on your
root disk. :)
 
J

James Kuyper

__NULL__ being a reserved word means that demons can fly out of the
programmer's nose when it is used.

No, that would be true only if the user code "declares or defines"
__NULL__ (7.1.3p2). Using NULL counts as neither a declaration nor a
definition of __NULL__. Since, in most contexts, using an identifier
that has neither been declared or defined is either a syntax error or a
constraint violation, user code which uses __NULL__ in any way would
also be a problem, though for a different reason.

However, for the purposes of 7.1.3p2, the expansion of NULL wouldn't
count as such a declaration or definition of __NULL__ even if the
expansion did happen to contain one, because the existence of that
feature is the implementation's responsibility, and it's the
implementation's additional responsibility to ensure that whatever NULL
expands to causes no such problems for strictly conforming code.

While that expansion may contain features that would render the behavior
undefined if they occurred in user code, when they occur in the
expansion of a C standard macro, the behavior is not allowed to be
anything inconsistent with what the C standard specifies for that macro.
What the standard specifies for NULL is a null pointer constant, and it
does not specify any relaxation of the rules determining what a null
pointer constant is.

In any event, the suggested implementation of NULL contained neither a
declaration nor a definition of __NULL__, just a use of __NULL__ as an
operand in an address constant expression. Since the suggested
implementation of NULL also specified that a declaration for __NULL__
appeared inside the standard header, it also doesn't count as a use of
an undeclared identifier.
 
J

James Kuyper

On a DeathStation 9000, &__NULL__ overwrites the partition table on your
root disk. :)

Except when it is found in the expansion of a standard macro. Otherwise
it's not fully conforming, and as we all know, the DS9000 is a paragon
of conformance. :)
 
K

Keith Thompson

Kenneth Brody said:
On 10/28/2011 4:13 PM, BartC wrote: [...]
Anyway there's a million ways a program can silently go wrong; A, B and N
might not be zero, but how do we know they are correct?

Having a program deliberately crash is a crude way of detecting some classes
of error.

"Deliberately crash" is a bit misleading. The crash, on those systems which
do crash, is a side effect of invoking UB. It's not like the implementation
has:

if ( s1 == NULL ) CrashProgram();

Actually, on some level within the operating system, there's code
that does something very much like that. A segmentation fault,
for example, is not just a random occurrence; substantial effort
went into designing the OS (and probably the hardware) so that
invalid memory accesses result in well-defined behavior. (That is,
well-defined by the OS, not by C.)

The point is (a) to alert the developer to the problem, so the code
can be corrected to avoid it, and (b) to prevent the program from
continuing to execute in an invalid state.
 
K

Keith Thompson

Kenneth Brody said:
I know of at least one system which would return zero, as the
system purposely reserves an all-bits-zero "page" of read-only
memory at address zero.

On some other system, it would return non-zero, as there was data
at address zero which would not be '\0'. (Unless "far" pointers
were being used, in which case, the byte may or may not have been
'\0'.)

However, on just about any system I use today, I would expect
the program to crash.

Yes, of course; the behavior is not defined by the language, so
any of those outcomes are possible.

But the point of the question was that gaoqiang was suggesting that
strcmp("", NULL) shouldn't cause a segmentation fault. If you
want the behavior to be defined, you're going to have to define
what the behavior is.
 
I

Ike Naar

On a DeathStation 9000, &__NULL__ overwrites the partition table on your
root disk. :)

Then probably NULL is not defined in terms of &__NULL__ on that platform.
 
B

Ben Bacarisse

Kenneth Brody said:
Does anyone know what K&R1 said about free(NULL)?

Nothing. The C library was not standardised then, and there were no
malloc and free function with any universal meaning.

free occurs in the index, but it refers to and example function used
to illustrate how allocation could be done (it's partner is alloc in the
examples).

<snip>
 
T

Tim Rentsch

ImpalerCore said:
What would you expect strcmp("", NULL) to return?

Ideally, I would love to see the behavior dependent on preprocessor
flag.

If DEBUG is defined,

Constraint violation: s2 != NULL, file example.c, line 9, function
strcmp
[crash]

If DEBUG is not defined: [crash]

[snip elaboration]

Bad idea to put that in the Standard. Better to leave it as
is, so different implementations can make their own choices.
Also, taking the long view, it seems better to leave open
the possibility of moving later to a safer set of choices (where
the behavior is defined) than to foreclose that possibility
by (no_pun_intended *) casting in stone the process-ending
result of crashing.

Editorial comment: the idea of making a constraint violation
dependent on the setting of a pre-processor variable is one
I find utterly repugnant. But hey, that's just my opinion. :)
 
T

Tim Rentsch

James Kuyper said:
On 11/03/2011 11:00 AM, Kenneth Brody wrote:
...
Note, too, that it's perfectly acceptable (as far as the C language itself
is concerned) to have NULL point to a "valid" address, as long as no valid
object can be at that address. ...

That is correct.
... For example, it would be legal (AFAIK) for
an implementation to do something like this:

extern char __NULL__;
#define NULL ((void *)(&__NULL__))

No, NULL is required to expand into a null pointer constant. A null
pointer constant is either "An integer constant expression with the
value 0, or such an expression cast to type void *," (6.3.2.3p3).

ICEs must have integer type; &__NULL__ has a pointer type. The operands
of an ICE "shall only have operands that are integer constants,
enumeration constants, character constants, sizeof expressions whose
results are integer constants, and floating constants that are the
immediate operands of casts." (6.6p6). __NULL__ qualifies as none of
those things. While "an implementation may accept other forms of
constant expressions" (6.6p10), those other forms will, by definition of
"other", not have the right form to qualify as any of the specific types
of constants specified in 6.6p6. [snip unrelated]

This conclusion is wrong. The phrase "other forms of constant
expressions" extendes to the different categories of CE described in
section 6.6, including integer constant expressions, as evidenced by
statements in the Rationale document and also (I believe but have not
taken the time to look up) several DR's. See for example the
discussion of 'offsetof()' in the Rationale document.
 
T

Tim Rentsch

James Kuyper said:
[snip]

However, null pointer constants are defined as involving an "integer
constant expression", a phrase whose meaning as a whole is defined in
6.6p6. [snip]

You are misunderstanding the license granted by 6.6p10, which
allows other forms of the various subtypes of constant expression,
including integer constant expressions. Again, look at the
statements made in the Rationale document.

Another problem with your theory (ie, that 6.6p10 applies only to
generic constant expressions, not to any of the subtypes listed in
6.6p10) is that then 6.6p10 wouldn't change anything. In all cases
where a program is required to use a constant expression, it is
required to use one of the subtypes of constant expression;
allowing 'other forms of constant expressions' only for "generic"
constant expressions, but not for the subtypes, is meaningless
because it would have no effect. (An argument could be made that
limiting 6.6p10 to just generic CE's would allow an implementation
to define some of the symbols given in 5.2.4.2.2 in such a way that
some otherwise-legal programs would exhibit constraint violations;
surely such a result cannot be the motivation for the statement in
6.6p10.) Since there is no reason to grant a meaningless or
useless licence, the statement in 6.6p10 must mean something other
than what you think it means.
 
T

Tim Rentsch

Ike Naar said:
Sorry for my previous post which did not contain any new text.
Something went wrong during posting.

In the meantime, James has already submitted a response
similar to what I was trying to submit:
Kaz's quoted statement about "contant integral expression" contradicts
6.6 p6 which states that an integer constant expression shall have
integer type, while &__NULL__ has type pointer-to-char.

The statements made in 6.6p6 need not apply to "other forms of
constant expressions" accepted under 6.6p10. That's the point
of putting in 6.6p10, to allow things that wouldn't be accepted
otherwise.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,952
Messages
2,570,115
Members
46,701
Latest member
mathewpark

Latest Threads

Top