Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Pointer to small amount of storage

Reply
Thread Tools

Pointer to small amount of storage

 
 
Old Wolf
Guest
Posts: n/a
 
      02-22-2008
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?



 
Reply With Quote
 
 
 
 
vippstar@gmail.com
Guest
Posts: n/a
 
      02-22-2008
On Feb 22, 4:37 pm, Old Wolf <(E-Mail Removed)> 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.
 
Reply With Quote
 
 
 
 
Malcolm McLean
Guest
Posts: n/a
 
      02-22-2008

"Old Wolf" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-22-2008
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
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      02-22-2008
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

 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      02-22-2008

"CBFalconer" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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

 
Reply With Quote
 
Old Wolf
Guest
Posts: n/a
 
      02-23-2008
On Feb 23, 4:33 am, Eric Sosman <(E-Mail Removed)> 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.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-23-2008
Old Wolf wrote:
> On Feb 23, 4:33 am, Eric Sosman <(E-Mail Removed)> 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
(E-Mail Removed)lid
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      02-24-2008
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

 
Reply With Quote
 
Harald van Dijk
Guest
Posts: n/a
 
      02-24-2008
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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

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

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


Similar Threads
Thread Thread Starter Forum Replies Last Post
FAQ 5.24 All I want to do is append a small amount of text to the end of a file. Do I still have to use locking? PerlFAQ Server Perl Misc 0 03-31-2011 04:00 AM
FAQ 5.24 All I want to do is append a small amount of text to the end of a file. Do I still have to use locking? PerlFAQ Server Perl Misc 0 02-01-2011 05:00 PM
On eating a small amount of crow spinoza1111 C Programming 0 11-16-2009 11:57 AM
OutOf Memory exception under Eclipse when using relatively small amount of heap lennyw@comcast.net Java 2 05-24-2006 08:13 PM
DVD Data only writes a small amount, and then freezes. xx75vulcan@juno.com DVD Video 0 03-17-2006 03:54 AM



Advertisments