Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Pointer to small amount of storage (http://www.velocityreviews.com/forums/t593453-pointer-to-small-amount-of-storage.html)

Old Wolf 02-22-2008 02:37 PM

Pointer to small amount of storage
 
Is there undefined behaviour here:

#include <stdlib.h>

int main()
{
short *p = malloc( sizeof *p );
long *q = (long *)p;
q;

return 0;
}

Rationale being that evaluating q causes undefined
behaviour because q is neither null, nor pointing to storage
suitable for an object of type *q.

Assuming so; then is it undefined before the `q;' line, or
is the code valid and q indeterminate?




vippstar@gmail.com 02-22-2008 03:21 PM

Re: Pointer to small amount of storage
 
On Feb 22, 4:37 pm, Old Wolf <oldw...@inspire.net.nz> wrote:
> Is there undefined behaviour here:
>
> #include <stdlib.h>
>
> int main()
> {
> short *p = malloc( sizeof *p );
> long *q = (long *)p;
> q;
>
> return 0;
>
> }
>
>
> Assuming so; then is it undefined before the `q;' line, or
> is the code valid and q indeterminate?


No, q becomes a dangling pointer (*IF* malloc does not return NULL)
after the assignment.

Malcolm McLean 02-22-2008 03:28 PM

Re: Pointer to small amount of storage
 

"Old Wolf" <oldwolf@inspire.net.nz> wrote in message
news:d75698b6-e95e-41eb-a70c-5762085a6e30@e60g2000hsh.googlegroups.com...
> Is there undefined behaviour here:
>
> #include <stdlib.h>
>
> int main()
> {
> short *p = malloc( sizeof *p );
> long *q = (long *)p;
> q;
>
> return 0;
> }
>
> Rationale being that evaluating q causes undefined
> behaviour because q is neither null, nor pointing to storage
> suitable for an object of type *q.
>
> Assuming so; then is it undefined before the `q;' line, or
> is the code valid and q indeterminate?
>

I think you've hit on an ambiguity in the standard.
Casting from a short * to a long * is not guaranteed to work. The short may
be improperly aligned, and so you could generate some sort of runtime error.

However the return from malloc() is guaranteed to be aligned for any
purpose. That leaves open the question of whether a too small allocation
can be assigned to the pointer. We could say it is OK because an allocation
of zero bytes can be assigned. However the zero allocation could fall under
the "one past" rule, in which case we are back to allowing the behaviour to
be undefined.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm



Eric Sosman 02-22-2008 03:33 PM

Re: Pointer to small amount of storage
 
Old Wolf wrote:
> Is there undefined behaviour here:
>
> #include <stdlib.h>
>
> int main()
> {
> short *p = malloc( sizeof *p );
> long *q = (long *)p;
> q;
>
> return 0;
> }
>
> Rationale being that evaluating q causes undefined
> behaviour because q is neither null, nor pointing to storage
> suitable for an object of type *q.
>
> Assuming so; then is it undefined before the `q;' line, or
> is the code valid and q indeterminate?


All's well. 6.3.2.3p7 tells us:

"A pointer to an object or incomplete type may be
converted to a pointer to a different object or
incomplete type. If the resulting pointer is not
correctly aligned for the pointed-to type, the
behavior is undefined. Otherwise, when converted
back again, the result shall compare equal to the
original pointer. [...]"

Since the value returned by malloc() is either NULL (in which
case the conversions certainly work) or correctly aligned for
any possible data type (7.20.3p1), the "otherwise" holds. If
`long *q = (long*)p;' were followed by `short *r = (short*)q;',
we would therefore have `r == p'. The requirement for `r == p'
could not hold if undefined behavior had occurred somewhere along
the way; therefore, there's no U.B.

Also, the evaluation `q;' produces no U.B. The fact that
a pointer is not dereferenceable does not imply that the pointer
value is indeterminate; the values NULL and "one past the end"
are examples of perfectly good non-dereferenceable pointers.

--
Eric Sosman
esosman@ieee-dot-org.invalid

CBFalconer 02-22-2008 07:38 PM

Re: Pointer to small amount of storage
 
Malcolm McLean wrote:
>

.... snip ...
>
> However the return from malloc() is guaranteed to be aligned for
> any purpose. That leaves open the question of whether a too small
> allocation can be assigned to the pointer. We could say it is OK
> because an allocation of zero bytes can be assigned. However the
> zero allocation could fall under the "one past" rule, in which
> case we are back to allowing the behaviour to be undefined.


No. The NULL, if returned from a zero allocation, is already one
past the assigned storage. It cannot be dereferenced.

The simplest method is not to allow a zero allocation to be made.
If you have access to the system code, and it does this, change it
to read:

void *malloc(size_t sz) {

if (!sz) sz++;
... the rest of the code ...
}

otherwise interpose something to do the same.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.



--
Posted via a free Usenet account from http://www.teranews.com


Malcolm McLean 02-22-2008 10:10 PM

Re: Pointer to small amount of storage
 

"CBFalconer" <cbfalconer@yahoo.com> wrote in message
news:47BF24C6.78DE171F@yahoo.com...
> Malcolm McLean wrote:
>>

> ... snip ...
>>
>> However the return from malloc() is guaranteed to be aligned for
>> any purpose. That leaves open the question of whether a too small
>> allocation can be assigned to the pointer. We could say it is OK
>> because an allocation of zero bytes can be assigned. However the
>> zero allocation could fall under the "one past" rule, in which
>> case we are back to allowing the behaviour to be undefined.

>
> No. The NULL, if returned from a zero allocation, is already one
> past the assigned storage. It cannot be dereferenced.
>

It's one past the last element of a zero-element array. Arguably.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm


Old Wolf 02-23-2008 10:08 PM

Re: Pointer to small amount of storage
 
On Feb 23, 4:33 am, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
> Old Wolf wrote:
> > Is there undefined behaviour here:

>
> > #include <stdlib.h>

>
> > int main()
> > {
> > short *p = malloc( sizeof *p );
> > long *q = (long *)p;
> > q;

>
> > return 0;
> > }

>
> All's well. 6.3.2.3p7 tells us:
>
> "A pointer to an object or incomplete type may be
> converted to a pointer to a different object or
> incomplete type. If the resulting pointer is not
> correctly aligned for the pointed-to type, the
> behavior is undefined. Otherwise, when converted
> back again, the result shall compare equal to the
> original pointer. [...]"


Good catch. How about this case:
long *q = malloc(2);

assuming sizeof(long) > 2 ? Now the 'defence' of
the pointer having to be able to be converted
back to short, is no longer available.

Eric Sosman 02-23-2008 10:36 PM

Re: Pointer to small amount of storage
 
Old Wolf wrote:
> On Feb 23, 4:33 am, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>> Old Wolf wrote:
>>> Is there undefined behaviour here:
>>> #include <stdlib.h>
>>> int main()
>>> {
>>> short *p = malloc( sizeof *p );
>>> long *q = (long *)p;
>>> q;
>>> return 0;
>>> }

>> All's well. 6.3.2.3p7 tells us:
>>
>> "A pointer to an object or incomplete type may be
>> converted to a pointer to a different object or
>> incomplete type. If the resulting pointer is not
>> correctly aligned for the pointed-to type, the
>> behavior is undefined. Otherwise, when converted
>> back again, the result shall compare equal to the
>> original pointer. [...]"

>
> Good catch. How about this case:
> long *q = malloc(2);
>
> assuming sizeof(long) > 2 ? Now the 'defence' of
> the pointer having to be able to be converted
> back to short, is no longer available.


But it can still be converted back to void* and must
then compare equal to the value of malloc():

void *v = malloc(2);
long *q = v;
assert ((void*)q == v);

.... so the argument still holds. Or so it seems to me.

--
Eric Sosman
esosman@ieee-dot-org.invalid

CBFalconer 02-24-2008 12:56 AM

Re: Pointer to small amount of storage
 
Old Wolf wrote:
>

.... snip ...
>
> Good catch. How about this case:
> long *q = malloc(2);
>
> assuming sizeof(long) > 2 ? Now the 'defence' of the pointer
> having to be able to be converted back to short, is no longer
> available.


That malloc doesn't assign enough space to hold the posited long.
Replace the '2' with "sizeof *q" (sans quotes) and all is well.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.



--
Posted via a free Usenet account from http://www.teranews.com


Harald van Dijk 02-24-2008 09:07 AM

Re: Pointer to small amount of storage
 
On Sat, 23 Feb 2008 19:56:44 -0500, CBFalconer wrote:
> Old Wolf wrote:
>>

> ... snip ...
>>
>> Good catch. How about this case:
>> long *q = malloc(2);
>>
>> assuming sizeof(long) > 2 ? Now the 'defence' of the pointer having to
>> be able to be converted back to short, is no longer available.

>
> That malloc doesn't assign enough space to hold the posited long.


That's the point. And the assignment's fine, since malloc's result is
properly aligned.


All times are GMT. The time now is 04:37 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.