printf("%p\n", (void *)0);

P

pete

a single consistent approach is used:
a null pointer argument is invalid whenever
the corresponding description of the behavior
implies that the argument is dereferenced.

In cases when it boils down to that the totality of the issue
is just that it confuses a couple of guys on c.l.c,
then the committee doesn't do anything.
 
P

pete

Actually dereferencing isn't required to disqualify NULL
as a valid argument value.
In C99, a call to qsort is valid when nmemb equals zero.
While qsort is neither allowed to call the comparison function
nor perform any rearrangement when nemb is zero,it may still
do things like calculate the address of the last element
or the one after that, unconditionally,
and (NULL + 0) and (NULL + 1) are undefined.
And so, NULL is an undefined value for base in a call to qsort,
even in C99, and even when nmemb equals zero.

void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
unsigned char *array, *after, *i, *j, *k, *p1, *p2, *end, swap;
size_t bytes;

array = base;
after = nmemb * size + array;
if (nmemb > (size_t)-1 / 3 - 1) {
nmemb = nmemb / 3 - 1;
} else {
nmemb = (nmemb * 3 + 1) / 7;
}
while (nmemb != 0) {
bytes = nmemb * size;
i = bytes + array;
do {
j = i - bytes;
if (compar(j, i) > 0) {
k = i;
do {
p1 = j;
p2 = k;
end = p2 + size;
do {
swap = *p1;
*p1++ = *p2;
*p2++ = swap;
} while (p2 != end);
if (bytes + array > j) {
break;
}
k = j;
j -= bytes;
} while (compar(j, k) > 0);
}
i += size;
} while (i != after);
nmemb = (nmemb * 3 + 1) / 7;
}
}
 
L

lawrence.jones

In comp.std.c pete said:
In cases when it boils down to that the totality of the issue
is just that it confuses a couple of guys on c.l.c,
then the committee doesn't do anything.

I wouldn't go that far, the committee generally does try to address
honest confusion of intelligent readers. But when it boils down to a
couple of guys on comp.std.c discussing the number of angels that can
dance on the head of a pin, the committee does indeed tend to ignore it.

Of course, I wouldn't dare try to suggest which of those more aptly
describes the issue at hand.

-Larry Jones

Santa's gonna skip this block for years. -- Calvin
 
T

Tim Rentsch

pete said:
Are you aware that pointer types are scalar types?
Your statement makes me think that you are not.

There are three major categories of types:
1 function types
2 incomplete types
3 object types

The only two incomplete types that I'm aware of are
void
and ones of the form
array[]

Also 'struct whatever' when a definition for the struct
has not yet been given. (And union too of course...)
 
P

pete

Tim said:
pete said:
Are you aware that pointer types are scalar types?
Your statement makes me think that you are not.

There are three major categories of types:
1 function types
2 incomplete types
3 object types

The only two incomplete types that I'm aware of are
void
and ones of the form
array[]

Also 'struct whatever' when a definition for the struct
has not yet been given. (And union too of course...)

Thank you.
I believe "definition" isn't the best word to use there.
 
I

infobahn

Douglas A. Gwyn said:
That counter-argument relies on "Each of the following
statements applies unless explicitly stated otherwise
in the detailed descriptions that follow: If an argument
to a function has an invalid value ..., the behavior is
undefined." Certainly if you examine the fprintf spec,
a null pointer value is not inherently invalid in that
context; that pointer argument is not required to point
at an object (unlike e.g. the arguments for strcpy).

Thanks for the clarification. This is the most convincing argument
that I've seen to date, and it strongly supports my hitherto
unwarranted assumption that a null pointer is valid in this context.

I'm pleased, because it means I don't have to go revisit my
entire code base!
 
I

infobahn

I wouldn't go that far, the committee generally does try to address
honest confusion of intelligent readers.

Glad to hear it. This was indeed honest confusion on my part, and
I like to fool myself that I'm an intelligent reader. I am now no
longer confused, thanks to Mr Gwyn's clarification.

It would be a shame if the committee did *not* try to address the
honest confusion of intelligent readers - but in this case it has
(albeit unofficially) done so.
 
K

Keith Thompson

Trevor L. Jackson said:
You can't directly. You can indirectly.

How?

In particular, the following invokes undefined behavior by evaluating
the stale pointer before passing it (directly) to realloc():

#include <stdlib.h>
#include <assert.h>

int main(void)
{
int *ptr = malloc(sizeof *ptr);
assert(ptr != NULL);
free(ptr);
/*
* ptr is now stale
*/
ptr = realloc(ptr, 2 * sizeof *ptr);
return 0;
}

How would you do this indirectly? (And why would you want to?)
 
T

Trevor L. Jackson, III

Keith said:
How?

In particular, the following invokes undefined behavior by evaluating
the stale pointer before passing it (directly) to realloc():

#include <stdlib.h>
#include <assert.h>

int main(void)
{
int *ptr = malloc(sizeof *ptr);
assert(ptr != NULL);
free(ptr);
/*
* ptr is now stale
*/
ptr = realloc(ptr, 2 * sizeof *ptr);
return 0;
}

How would you do this indirectly? (And why would you want to?)

I'm interpreting your question to be "how would you do this indirectly
_to_realloc()_." You can't.

As for the more general question of passing stale pointers to arbitrary
functions, obviously you just pass the address of the pointer.

Why would you want to? Well, C is a system implementation language.
And C is not the only language that can handle pointers. For instance,
on a system with memory management hardware one might want to pass the
address of free()'d entities to a mmgt function so that it could stop
caching, buffering, synchronizing, unmap, or whatever it does to memory
at the indicated address. Does a typical C implementation support that?
Of course not. Should it? almost certainly not. Should it forbid it?
Absolutely not.

Are stale pointers useful? Quite rarely. But when you need it you need it.

/tj3
 
C

CBFalconer

Trevor L. Jackson said:
.... snip ...

Why would you want to? Well, C is a system implementation language.
And C is not the only language that can handle pointers. For instance,
on a system with memory management hardware one might want to pass the
address of free()'d entities to a mmgt function so that it could stop
caching, buffering, synchronizing, unmap, or whatever it does to memory
at the indicated address. Does a typical C implementation support that?
Of course not. Should it? almost certainly not. Should it forbid it?
Absolutely not.

Absolutely yes. The only module that can handle your scenario
properly is the malloc module, which is part of the runtime system
for very good reasons. C knows nothing whatsoever about caching,
buffering, etc. This has nothing to do with the language the
malloc module is written in, except that we know it cannot be
conforming C.
 
K

Keith Thompson

Trevor L. Jackson said:
I'm interpreting your question to be "how would you do this indirectly
_to_realloc()_." You can't.

Ok. I assumed, from the context, that you were saying a stale pointer
can be passed to realloc() indirectly. You meant that it can be
passed to some arbitrary function indirectly, which of course is true.
(If nothing else, you can break it down to an array of unsigned char.)
And yes, there could be any number of reasons why you'd want to do
this (just to see what stale pointers look like, if nothing else).
 
T

Tim Rentsch

pete said:
Tim said:
pete said:
The only two incomplete types that I'm aware of are
void
and ones of the form
array[]

Also 'struct whatever' when a definition for the struct
has not yet been given. (And union too of course...)

Thank you.
I believe "definition" isn't the best word to use there.

Right. The language used in the standard document is different - it
speaks of a struct or union type having "unknown content", and the
appearance a type declaration with stuff between the braces as
"defining the content" of a struct or union type, and struct/union
tags are only declared, whether or not they have their content defined
with a '{ member-list }' clause.

Of course, what I meant was that something like 'struct whatever' would
declare the type, and 'struct whatever { int foo; }' would define the
type, and probably that's what most people understood. But you're
right that it doesn't match the language of the standard document.

So my statement might be emended as:

Also 'struct whatever' when the struct content has not yet been
defined. (And union too of course...)
 
S

Stephen Sprunk

Any added features such as those described should either be disabled prior
to calling free() or included in the implementation of free() itself.
Absolutely yes. The only module that can handle your scenario
properly is the malloc module, which is part of the runtime system
for very good reasons. C knows nothing whatsoever about caching,
buffering, etc. This has nothing to do with the language the
malloc module is written in, except that we know it cannot be
conforming C.

That user code (perhaps the code for the malloc module itself) calls
non-standard functions of the OS is no reason for the implementation to
refuse to compile that code. It may invoke UB or IDB, but it's not the
compiler's job to tell the user he _can't_ do that, though it might be
useful for it to warn the user that doing so relies on UB or IDB.
C knows nothing whatsoever about caching, buffering, etc. This has
nothing to do with the language the malloc module is written in,
except that we know it cannot be conforming C.

Are you saying that it is impossible to implement malloc() et al in
conforming C? Or just the extra features Trevor listed?

S
 
T

Trevor L. Jackson, III

CBFalconer said:
:

... snip ...



Absolutely yes. The only module that can handle your scenario
properly is the malloc module, which is part of the runtime system
for very good reasons. C knows nothing whatsoever about caching,
buffering, etc.

C does not. C applications may. And the malloc module will probably be
written, you geuessed it, C.
This has nothing to do with the language the
malloc module is written in, except that we know it cannot be
conforming C.

Why not?
 
T

Trevor L. Jackson, III

Keith said:
Ok. I assumed, from the context, that you were saying a stale pointer
can be passed to realloc() indirectly.

Sorry if I mislead you. I'll try to be more precise in the future.
You meant that it can be
passed to some arbitrary function indirectly, which of course is true.
(If nothing else, you can break it down to an array of unsigned char.)

Good point. I should have mentioned that.
 
J

James Kuyper

Stephen said:
Are you saying that it is impossible to implement malloc() et al in
conforming C? Or just the extra features Trevor listed?

That's what he's said, but it's wrong - conforming C code has very few
limitations on what it can do (off hand, I can't think of any). If you
change "conforming" to "strictly conforming" his statement becomes more
accurate. The fundamental problem is that strictly conforming C programs
have only one possible mechanism for obtaining a pointer to a block of
memory that is guaranteed to have universal alignment (correct alignment
for all possible objects). That method is to call malloc(). If written
in strictly conforming C code, malloc() has no way to do that (a
recursive call to malloc() is obviously not a solution to the problem),
yet it is required by the standard to return such a pointer.

For practical purposes, an implementation of malloc() could be written
that allocates from a fixed static array of memory. The array would have
a union type, where the union has members of many different types. The
wider the variety of types in the union, the more likely it is to have
universal alignment. In practice, if the union contains short, int,
long, long long, float, double, long double, void*, and void(*)(void),
it's got a pretty good chance of having universal alignment. However,
there's no finite set of types which is guaranteed by the standard to
give such a union universal alignment.
 
P

pete

James Kuyper wrote:
For practical purposes, an implementation of malloc() could be written
that allocates from a fixed static array of memory.
The array would have
a union type, where the union has members of many different types. The
wider the variety of types in the union, the more likely it is to have
universal alignment. In practice, if the union contains short, int,
long, long long, float, double, long double, void*, and void(*)(void),
it's got a pretty good chance of having universal alignment. However,
there's no finite set of types which is guaranteed by the standard to
give such a union universal alignment.

That wouldn't work.
In order to access the array of unions, as an array of shorts,
the union has to be aligned for an array of shorts,
not merely aligned for short.
 
C

CBFalconer

Stephen said:
.... snip ...


Are you saying that it is impossible to implement malloc() et al in
conforming C? Or just the extra features Trevor listed?

Yes. Both. The fundamental bind is alignment. After that comes
practicality. Otherwise you could declare:

static unsigned char programPseudoHeap[GARGANTUAN_NUMBER];

and dole stuff out from there. That would mean helloworld would
require at least GARGANTUAN_NUMBER bytes of data space. Seems like
a waste. However the technique is usable with advance alignment
knowledge to thrash out new versions of malloc on a particular
system. See nmalloc.zip on my download section for an example with
all debuggery enabled.
 
K

Keith Thompson

pete said:
That wouldn't work.
In order to access the array of unions, as an array of shorts,
the union has to be aligned for an array of shorts,
not merely aligned for short.

I don't believe it's possible for a short and an array of shorts to
have different required alignments. If short is 16 bits, a compiler
might choose to use, say, 32-bit alignment for arrays of shorts, but
it still has to be able to access an array of shorts that's 16-bit
aligned. For some purposes, a single short object is equivalent to an
array of 1 short.
 

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,772
Messages
2,569,593
Members
45,111
Latest member
KetoBurn
Top