[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Re: Bounds Checking as Undefined Behaviour?

Shao Miller

6/8/2011 2:53:00 PM

Good day, folks!

With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather for reporting his concerns:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/...

I am wondering about whether or not the behaviour is defined for the noted line (or in general) in the code below:

/* Shao Miller, 2011 */
void * ptr_equ(const void * p, const void * q) {
typedef unsigned char * bp;
void * result;
bp pi, qi, ri, re;
pi = (bp)&p; qi = (bp)&q; ri = (bp)&result;
re = ri + sizeof result;
while (ri < re)
/* Defect Report #260: "Provenance" */
*ri++ = *pi++ & *qi++;
pi = (bp)&p; qi = (bp)&q; ri = (bp)&result;
while (ri < re)
if (*ri != *pi++ || *ri++ != *qi++)
return (void *)0;
return result;
}

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int iaa[2][2] = {{1,2},{3,4}};
int * ip;

printf(
"iaa: {{%d,%d},{%d,%d}}\n",
iaa[0][0],
iaa[0][1],
iaa[1][0],
iaa[1][1]
);
/* &iaa[0][2] == &iaa[1][0] ? */
ip = ptr_equ(iaa[0] + 2, iaa[1]);
if (!ip) {
puts("Pointers have different object representation!");
return EXIT_FAILURE;
}
puts("Pointers have the same object representation");
/* Does the next line have undefined behaviour? */
*ip = 5;
printf(
"iaa: {{%d,%d},{%d,%d}}\n",
iaa[0][0],
iaa[0][1],
iaa[1][0],
iaa[1][1]
);
return EXIT_SUCCESS;
}
8 Answers

Tim Rentsch

6/8/2011 7:37:00 PM

0

Shao Miller <sha0.miller@gmail.com> writes:

> With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather for reporting his concerns:
>
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/...
>
> I am wondering about whether or not the behaviour is defined
> [..snip..]

comp.std.c is a better venue for this question.

io_x

6/9/2011 6:49:00 AM

0


"Shao Miller" <sha0.miller@gmail.com> ha scritto nel messaggio
news:27fa82a4-d89c-4b75-a483-cd0e1ae272cd@glegroupsg2000goo.googlegroups.com...
> Good day, folks!
>
> With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather for
> reporting his concerns:
>
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/...
>
> I am wondering about whether or not the behaviour is defined for the noted
> line (or in general) in the code below:
>
> /* Shao Miller, 2011 */
> void * ptr_equ(const void * p, const void * q) {
> typedef unsigned char * bp;
> void * result;
> bp pi, qi, ri, re;
> pi = (bp)&p; qi = (bp)&q; ri = (bp)&result;
> re = ri + sizeof result;
> while (ri < re)
> /* Defect Report #260: "Provenance" */
> *ri++ = *pi++ & *qi++;
> pi = (bp)&p; qi = (bp)&q; ri = (bp)&result;
> while (ri < re)
> if (*ri != *pi++ || *ri++ != *qi++)
> return (void *)0;
> return result;
> }
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void) {
> int iaa[2][2] = {{1,2},{3,4}};
> int * ip;
>
> printf(
> "iaa: {{%d,%d},{%d,%d}}\n",
> iaa[0][0],
> iaa[0][1],
> iaa[1][0],
> iaa[1][1]
> );
> /* &iaa[0][2] == &iaa[1][0] ? */
> ip = ptr_equ(iaa[0] + 2, iaa[1]);
> if (!ip) {
> puts("Pointers have different object representation!");
> return EXIT_FAILURE;
> }
> puts("Pointers have the same object representation");
> /* Does the next line have undefined behaviour? */
> *ip = 5;
> printf(
> "iaa: {{%d,%d},{%d,%d}}\n",
> iaa[0][0],
> iaa[0][1],
> iaa[1][0],
> iaa[1][1]
> );
> return EXIT_SUCCESS;
> }
it is unreadable, for i think doing something it seems easy





Shao Miller

6/9/2011 1:42:00 PM

0

On 6/9/2011 02:48, io_x wrote:
> "Shao Miller"<sha0.miller@gmail.com> ha scritto nel messaggio
> news:27fa82a4-d89c-4b75-a483-cd0e1ae272cd@glegroupsg2000goo.googlegroups.com...
>> Good day, folks!
>>
>> With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather for
>> reporting his concerns:
>>
>> http://www.open-std.org/jtc1/sc22/wg14/www/docs/...
>>
>> I am wondering about whether or not the behaviour is defined for the noted
>> line (or in general) in the code below:
>>
>> [...code...]
>>
> it is unreadable, for i think doing something it seems easy
>

Very well. I've included a version below which is hopefully more
readable for you. I would expect that for many implementations, the
entire 'obj_ptr_equ' function could be optimized to:

(!memcmp(&ptr_one, &ptr_two, sizeof ptr_one) ? ptr_one : 0)

and for some other implementations, it could be optimized to:

((ptr_one == ptr_two) ? ptr_one : 0)

But anyway, here's the code:

/* Shao Miller, 2011 */
void * obj_ptr_equ(const void * ptr_one, const void * ptr_two) {
typedef unsigned char * byte_ptr_t;
void * result;
/* Points into the object representation of 'ptr_one' */
byte_ptr_t ptr_into_ptr_one;
/* Points into the object representation of 'ptr_two' */
byte_ptr_t ptr_into_ptr_two;
/* Points into the object representation of 'result' */
byte_ptr_t ptr_into_result;
/* Points one past the last byte of 'result' */
byte_ptr_t ptr_to_one_past_result;

/*
* Point to the first byte of:
* - 'ptr_one'
* - 'ptr_two'
* - 'result'
*/
ptr_into_ptr_one = (byte_ptr_t)&ptr_one;
ptr_into_ptr_two = (byte_ptr_t)&ptr_two;
ptr_into_result = (byte_ptr_t)&result;

/* Note the address of one past the last byte of 'result' */
ptr_to_one_past_result = ptr_into_result + sizeof result;

/*
* For each byte of 'result', make it the bitwise AND
* of the corresponding bytes of 'ptr_one' and 'ptr_two'
*/
while (ptr_into_result < ptr_to_one_past_result) {
/* Defect Report #260: "Provenance" */
*ptr_into_result = *ptr_into_ptr_one & *ptr_into_ptr_two;
ptr_into_result++;
ptr_into_ptr_one++;
ptr_into_ptr_two++;
}

/*
* Point to the first byte of:
* - 'ptr_one'
* - 'ptr_two'
* - 'result'
*/
ptr_into_ptr_one = (byte_ptr_t)&ptr_one;
ptr_into_ptr_two = (byte_ptr_t)&ptr_two;
ptr_into_result = (byte_ptr_t)&result;

/*
* For each byte of 'result', compare it with the bytes
* of 'ptr_one' and 'ptr_two'. If we find a mis-match,
* return a null pointer value to the caller
*/
while (ptr_into_result < ptr_to_one_past_result) {
if (*ptr_into_result != *ptr_into_ptr_one)
return (void *)0;
if (*ptr_into_result != *ptr_into_ptr_two)
return (void *)0;
ptr_into_result++;
ptr_into_ptr_one++;
ptr_into_ptr_two++;
}

/*
* If we get here, the object representations for:
* - 'ptr_one'
* - 'ptr_two'
* - 'result'
* are the same. Return the bitwise AND result
*/
return result;
}

#include <stdio.h>
#include <stdlib.h>

int main(void) {
int array_of_array_of_int[2][2] = {{1,2},{3,4}};
int * ip;

printf(
"array_of_array_of_int: {{%d,%d},{%d,%d}}\n",
array_of_array_of_int[0][0],
array_of_array_of_int[0][1],
array_of_array_of_int[1][0],
array_of_array_of_int[1][1]
);
/* &array_of_array_of_int[0][2] == &array_of_array_of_int[1][0] ? */
ip = obj_ptr_equ(
&array_of_array_of_int[0][2],
&array_of_array_of_int[1][0]
);
if (!ip) {
puts("Pointers have different object representation!");
return EXIT_FAILURE;
}
puts("Pointers have the same object representation");
/* Does the next line have undefined behaviour? */
*ip = 5;
printf(
"array_of_array_of_int: {{%d,%d},{%d,%d}}\n",
array_of_array_of_int[0][0],
array_of_array_of_int[0][1],
array_of_array_of_int[1][0],
array_of_array_of_int[1][1]
);
return EXIT_SUCCESS;
}

io_x

6/9/2011 4:35:00 PM

0


"Shao Miller" <sha0.miller@gmail.com> ha scritto nel messaggio
news:27fa82a4-d89c-4b75-a483-cd0e1ae272cd@glegroupsg2000goo.googlegroups.com...
> Good day, folks!
>
> With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather for
> reporting his concerns:
>
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/...
>
> I am wondering about whether or not the behaviour is defined for the noted
> line (or in general) in the code below:
>
> /* Shao Miller, 2011 */
> void * ptr_equ(const void * p, const void * q) {
> typedef unsigned char * bp;
> void * result;
> bp pi, qi, ri, re;
> pi = (bp)&p; qi = (bp)&q; ri = (bp)&result;
> re = ri + sizeof result;
> while (ri < re)
> /* Defect Report #260: "Provenance" */
> *ri++ = *pi++ & *qi++;
> pi = (bp)&p; qi = (bp)&q; ri = (bp)&result;
> while (ri < re)
> if (*ri != *pi++ || *ri++ != *qi++)
> return (void *)0;
> return result;
> }
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void) {
> int iaa[2][2] = {{1,2},{3,4}};
> int * ip;
>
> printf(
> "iaa: {{%d,%d},{%d,%d}}\n",
> iaa[0][0],
> iaa[0][1],
> iaa[1][0],
> iaa[1][1]
> );
> /* &iaa[0][2] == &iaa[1][0] ? */
> ip = ptr_equ(iaa[0] + 2, iaa[1]);
> if (!ip) {
> puts("Pointers have different object representation!");
> return EXIT_FAILURE;
> }
> puts("Pointers have the same object representation");
> /* Does the next line have undefined behaviour? */
> *ip = 5;
> printf(
> "iaa: {{%d,%d},{%d,%d}}\n",
> iaa[0][0],
> iaa[0][1],
> iaa[1][0],
> iaa[1][1]
> );
> return EXIT_SUCCESS;
> }

i don't know if yuour code has some UB; i think the
below has some less UBs of your

the problem could be sizeof(void*)!=sizeof(int*)
because result is void* but ip is int*
but i'm not much sure of that

-------------------------------
#define u8 unsigned char
#define u32 unsigned

/* Shao Miller, 2011 */
u32* ptr_equ(u32* p, u32* q)
{u32 *result;
u8 *pi, *qi, *ri, *re;

pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
re=ri + sizeof result;
while(ri<re)
*ri++ = *pi++ & *qi++;
pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
/* if( result != q ) return 0 */
while(ri<re)
if(*ri!=*pi++ || *ri++!=*qi++)
return 0;
return result;
}

#include <stdio.h>
#include <stdlib.h>

int main(void)
{u32 iaa[2][2] = {{5,6},{7,8}};
u32 *ip;

printf("iaa: {{%u,%u},{%u,%u}}\n",
iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
/* &iaa[0][2] == &iaa[1][0] ?
iaa[0][0], iaa[0][1], iaa[1][0], iaa[1][1]
io> iaa[0]+2 == iaa[1] i see it in the debugger
*/

ip=ptr_equ(iaa[0] + 2, iaa[1]);
if(!ip){puts("Pointers have different object representation!");
return EXIT_FAILURE;}
puts("Pointers have the same object representation");

/* Does the next line have undefined behaviour? */
/* io> here not */
*ip = 5;
printf("iaa: {{%u,%u},{%u,%u}}\n",
iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
return EXIT_SUCCESS;
}



Shao Miller

6/9/2011 5:55:00 PM

0

On 6/9/2011 12:35, io_x wrote:
> "Shao Miller"<sha0.miller@gmail.com> ha scritto nel messaggio
> news:27fa82a4-d89c-4b75-a483-cd0e1ae272cd@glegroupsg2000goo.googlegroups.com...
>> Good day, folks!
>>
>> With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather for
>> reporting his concerns:
>>
>> http://www.open-std.org/jtc1/sc22/wg14/www/docs/...
>>
>> I am wondering about whether or not the behaviour is defined for the noted
>> line (or in general) in the code below:
>>
>> [...code...]
>
> i don't know if yuour code has some UB; i think the
> below has some less UBs of your
>

As in 0 points of undefined behaviour? As far as I know, there was only
one potential point for undefined behaviour: On the line marked "Does
the next line have undefined behaviour?" If your code below has "less,"
then I think that would mean zero points of undefined behaviour.

> the problem could be sizeof(void*)!=sizeof(int*)

In whose code? Yours (below) or mine? I don't see you using 'void *'
below. If you mean mine, 'ptr_equ' (renamed more accurately to
'obj_ptr_equ' in another post) takes two 'void *'s. It tests their
object representations, not the object representations of the original
'int *'-typed arguments. Size differences between the pointer types
shouldn't make any difference.

> because result is void* but ip is int*

If you mean that the result of 'ptr_equ' is assigned to 'ip' in my code,
yes, that conversion is defined. (As far as I know.) 'ip' can have a
completely different object representation.

> but i'm not much sure of that
>
> -------------------------------
> #define u8 unsigned char
> #define u32 unsigned
>

Do you use these macros because the numbers '8' and '32' and meaningful
for the implementations you frequently use? Or do you use '8' because
'CHAR_BIT' must be '8' at a minimum? Or some other reason?

> /* Shao Miller, 2011 */

No need to include the line above, since it's your code. ;)

> u32* ptr_equ(u32* p, u32* q)

This function takes and returns 'unsigned int *', instead of 'void *'.
If I want to use the function for 'struct foo *', that means I have to use:

foop=(struct foo *)ptr_equ((u32*)foo_ptr_one, (u32*)foo_ptr_two);

But the cast '(u32*)foo_ptr_one' is unsafe if the first member of
'struct foo' is not a 'u32'; the alignment requirements can be
different, for one example.

> {u32 *result;
> u8 *pi, *qi, *ri, *re;
>
> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
> re=ri + sizeof result;
> while(ri<re)
> *ri++ = *pi++& *qi++;
> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
> /* if( result != q ) return 0 */

I know you've commented it out, but wish to point out that the code:

if( result != q) return 0;

is not safe. The object representations of two 'u32*' pointers have
been "merged" together with bitwise AND. But if they were unequal, the
resulting object representation might not be valid when interpreted as a
'u32*' pointer. 'if ( result' interprets it as a 'u32*' pointer value,
which might not be a valid value. Fortunately, you have it commented
out. :)

> while(ri<re)
> if(*ri!=*pi++ || *ri++!=*qi++)
> return 0;
> return result;
> }
>
> #include<stdio.h>
> #include<stdlib.h>
>
> int main(void)
> {u32 iaa[2][2] = {{5,6},{7,8}};
> u32 *ip;
>

Are they playing catch with the pointer star? (Just kidding. Hee hee hee.)

> printf("iaa: {{%u,%u},{%u,%u}}\n",
> iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
> /*&iaa[0][2] ==&iaa[1][0] ?
> iaa[0][0], iaa[0][1], iaa[1][0], iaa[1][1]
> io> iaa[0]+2 == iaa[1] i see it in the debugger
> */
>
> ip=ptr_equ(iaa[0] + 2, iaa[1]);
> if(!ip){puts("Pointers have different object representation!");
> return EXIT_FAILURE;}
> puts("Pointers have the same object representation");
>
> /* Does the next line have undefined behaviour? */
> /* io> here not */
> *ip = 5;
> printf("iaa: {{%u,%u},{%u,%u}}\n",
> iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
> return EXIT_SUCCESS;
> }

Your code explicitly examines the object representations of 'u32*'-typed
pointers, rather than of converted-to-'void *' pointers. Ok.

But here's a question for you: Does 'ip' point to one past the 'iaa[0]'
array, or does it point to the first element of the 'iaa[1]' array? If
the former, '*ip = 5;' is undefined behaviour (by the Standard). If the
latter, everything's fine. If both, then is the behaviour defined or
undefined? If neither, then what does it point to?

Thanks for the feed-back!

io_x

6/9/2011 7:01:00 PM

0


"Shao Miller" <sha0.miller@gmail.com> ha scritto nel messaggio
news:isr18q$efg$1@dont-email.me...
> On 6/9/2011 12:35, io_x wrote:
>> "Shao Miller"<sha0.miller@gmail.com> ha scritto nel messaggio
>> news:27fa82a4-d89c-4b75-a483-cd0e1ae272cd@glegroupsg2000goo.googlegroups.com...
>>> Good day, folks!
>>>
>>> With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather
>>> for
>>> reporting his concerns:
>>>
>>> http://www.open-std.org/jtc1/sc22/wg14/www/docs/...
>>>
>>> I am wondering about whether or not the behaviour is defined for the noted
>>> line (or in general) in the code below:
>>>
>>> [...code...]
>>
>> i don't know if yuour code has some UB; i think the
>> below has some less UBs of your
>>
>
> As in 0 points of undefined behaviour? As far as I know, there was only one
> potential point for undefined behaviour: On the line marked "Does the next
> line have undefined behaviour?" If your code below has "less," then I think
> that would mean zero points of undefined behaviour.
>
>> the problem could be sizeof(void*)!=sizeof(int*)
>
> In whose code? Yours (below) or mine?

your code, has
re = ri + sizeof result;
while (ri < re)
/* Defect Report #260: "Provenance" */
*ri++ = *pi++ & *qi++;
where 'ri' point to a void*, 'pi' and 'qi' point to
one int* pointer
and the loop, loop for sizeof(result)==sizeof(void*)
times

if sizeof(void*)>sizeof(int*) that above 'pi', 'qi' read something out the
a int* pointer

> I don't see you using 'void *' below. If you mean mine, 'ptr_equ' (renamed
> more accurately to 'obj_ptr_equ' in another post) takes two 'void *'s. It
> tests their object representations, not the object representations of the
> original 'int *'-typed arguments. Size differences between the pointer types
> shouldn't make any difference.

yes

>> because result is void* but ip is int*
>
> If you mean that the result of 'ptr_equ' is assigned to 'ip' in my code, yes,
> that conversion is defined. (As far as I know.) 'ip' can have a completely
> different object representation.
>
>> but i'm not much sure of that
>>
>> -------------------------------
>> #define u8 unsigned char
>> #define u32 unsigned
>>
>
> Do you use these macros because the numbers '8' and '32' and meaningful for
> the implementations you frequently use? Or do you use '8' because 'CHAR_BIT'
> must be '8' at a minimum? Or some other reason?

i whould rewrite as
#include <stdint.h>

#define u32 uint32_t
#define u8 uint8_t


>> /* Shao Miller, 2011 */
>
> No need to include the line above, since it's your code. ;)
>
>> u32* ptr_equ(u32* p, u32* q)
>
> This function takes and returns 'unsigned int *', instead of 'void *'. If I
> want to use the function for 'struct foo *', that means I have to use:
>
> foop=(struct foo *)ptr_equ((u32*)foo_ptr_one, (u32*)foo_ptr_two);

ok i try
/* Shao Miller, 2011 */
u8* ptr_equ(u8* p, u8* q, u32 v)
{u8 *result;
u8 *pi, *qi, *ri, *re;

/* where v is sizeof(type) and -1 means error */
if(v!=sizeof(u8*)) return -1;

pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
re=ri + sizeof result;
while(ri<re)
*ri++ = *pi++ & *qi++;
pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
while(ri<re)
if(*ri!=*pi++ || *ri++!=*qi++)
return 0;
return result;
}


> But the cast '(u32*)foo_ptr_one' is unsafe if the first member of 'struct foo'
> is not a 'u32'; the alignment requirements can be different, for one example.

ok

>> {u32 *result;
>> u8 *pi, *qi, *ri, *re;
>>
>> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
>> re=ri + sizeof result;
>> while(ri<re)
>> *ri++ = *pi++& *qi++;
>> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
>> /* if( result != q ) return 0 */
>
> I know you've commented it out, but wish to point out that the code:
>
> if( result != q) return 0;
>
> is not safe. The object representations of two 'u32*' pointers have been
> "merged" together with bitwise AND. But if they were unequal, the resulting
> object representation might not be valid when interpreted as a 'u32*' pointer.
> 'if ( result' interprets it as a 'u32*' pointer value, which might not be a
> valid value. Fortunately, you have it commented out. :)

i not understand it well

>> while(ri<re)
>> if(*ri!=*pi++ || *ri++!=*qi++)
>> return 0;
>> return result;
>> }
>>
>> #include<stdio.h>
>> #include<stdlib.h>
>>
>> int main(void)
>> {u32 iaa[2][2] = {{5,6},{7,8}};
>> u32 *ip;
>>
>
> Are they playing catch with the pointer star? (Just kidding. Hee hee hee.)
>
>> printf("iaa: {{%u,%u},{%u,%u}}\n",
>> iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
>> /*&iaa[0][2] ==&iaa[1][0] ?
>> iaa[0][0], iaa[0][1], iaa[1][0], iaa[1][1]
>> io> iaa[0]+2 == iaa[1] i see it in the debugger
>> */
>>
>> ip=ptr_equ(iaa[0] + 2, iaa[1]);
>> if(!ip){puts("Pointers have different object representation!");
>> return EXIT_FAILURE;}
>> puts("Pointers have the same object representation");
>>
>> /* Does the next line have undefined behaviour? */
>> /* io> here not */
>> *ip = 5;
>> printf("iaa: {{%u,%u},{%u,%u}}\n",
>> iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
>> return EXIT_SUCCESS;
>> }
>
> Your code explicitly examines the object representations of 'u32*'-typed
> pointers, rather than of converted-to-'void *' pointers. Ok.
>
> But here's a question for you: Does 'ip' point to one past the 'iaa[0]'

ip here point to &(iaa[1][0]) aligned to u32 (the print say so)

> array, or does it point to the first element of the 'iaa[1]' array?

yes point to iaa[1] (debugger say so)

------------
iaa: {{5,6},{7,8}}
Pointers have the same object representation
iaa: {{5,6},{5,8}}
------------
so the element of *ip here is iaa[1][0]

> If the former, '*ip = 5;' is undefined behaviour (by the Standard). If the
> latter, everything's fine. If both, then is the behaviour defined or
> undefined? If neither, then what does it point to?
>
> Thanks for the feed-back!




Shao Miller

6/10/2011 4:33:00 AM

0

On 6/9/2011 2:00 PM, io_x wrote:
> "Shao Miller"<sha0.miller@gmail.com> ha scritto nel messaggio
> news:isr18q$efg$1@dont-email.me...
>> On 6/9/2011 12:35, io_x wrote:
>>> "Shao Miller"<sha0.miller@gmail.com> ha scritto nel messaggio
>>> news:27fa82a4-d89c-4b75-a483-cd0e1ae272cd@glegroupsg2000goo.googlegroups.com...
>>>> Good day, folks!
>>>>
>>>> With thanks to Wojtek Lerch for pointing out DR #206, and to Clive Feather
>>>> for
>>>> reporting his concerns:
>>>>
>>>> http://www.open-std.org/jtc1/sc22/wg14/www/docs/...
>>>>
>>>> I am wondering about whether or not the behaviour is defined for the noted
>>>> line (or in general) in the code below:
>>>>
>>>> [...code...]
>>>
>>> i don't know if yuour code has some UB; i think the
>>> below has some less UBs of your
>>>
>>
>> As in 0 points of undefined behaviour? As far as I know, there was only one
>> potential point for undefined behaviour: On the line marked "Does the next
>> line have undefined behaviour?" If your code below has "less," then I think
>> that would mean zero points of undefined behaviour.
>>
>>> the problem could be sizeof(void*)!=sizeof(int*)
>>
>> In whose code? Yours (below) or mine?
>
> your code, has
> re = ri + sizeof result;
> while (ri< re)
> /* Defect Report #260: "Provenance" */
> *ri++ = *pi++& *qi++;
> where 'ri' point to a void*, 'pi' and 'qi' point to
> one int* pointer

'pi' does not point to an 'int *' and 'qi' does not point to an 'int *'.
'pi' points to a 'void *' and 'qi' points to a 'void *'.

When the function is called:

ip = obj_ptr_equ(&iaa[0][2], &iaa[1][0]);

'&iaa[0][2]' is an 'int *'-typed value like '1 + 1' is an 'int'-typed
value. But because the function is declared to have 'void *'
parameters, the 'int *'-typed arguments are converted to 'void *'-typed
values, then those 'void *'-typed values become the values of the 'void
*'-typed parameters, not the original 'int *' values.

('&iaa[0][2]' used for brevity, though the original code had 'iaa[0] + 2'.)

> and the loop, loop for sizeof(result)==sizeof(void*)
> times
>

Right. 'p', 'q', 'result' are all 'void *'-typed objects with the same
size.

> if sizeof(void*)>sizeof(int*) that above 'pi', 'qi' read something out the
> a int* pointer
>

See above.

>> I don't see you using 'void *' below. If you mean mine, 'ptr_equ' (renamed
>> more accurately to 'obj_ptr_equ' in another post) takes two 'void *'s. It
>> tests their object representations, not the object representations of the
>> original 'int *'-typed arguments. Size differences between the pointer types
>> shouldn't make any difference.
>
> yes
>

Ok.

>>> because result is void* but ip is int*
>>
>> If you mean that the result of 'ptr_equ' is assigned to 'ip' in my code, yes,
>> that conversion is defined. (As far as I know.) 'ip' can have a completely
>> different object representation.
>>
>>> but i'm not much sure of that
>>>
>>> -------------------------------
>>> #define u8 unsigned char
>>> #define u32 unsigned
>>>
>>
>> Do you use these macros because the numbers '8' and '32' and meaningful for
>> the implementations you frequently use? Or do you use '8' because 'CHAR_BIT'
>> must be '8' at a minimum? Or some other reason?
>
> i whould rewrite as
> #include<stdint.h>
>
> #define u32 uint32_t
> #define u8 uint8_t
>
>

Ok, but to my knowledge, 'uint32_t' needn't be available for some C89
implementations. I was trying to understand why you were using specific
numbers like '8' and '32', but I guess it doesn't really matter. :)

>>> /* Shao Miller, 2011 */
>>
>> No need to include the line above, since it's your code. ;)
>>
>>> u32* ptr_equ(u32* p, u32* q)
>>
>> This function takes and returns 'unsigned int *', instead of 'void *'. If I
>> want to use the function for 'struct foo *', that means I have to use:
>>
>> foop=(struct foo *)ptr_equ((u32*)foo_ptr_one, (u32*)foo_ptr_two);
>
> ok i try
> /* Shao Miller, 2011 */

/* io_x, 2011 */

> u8* ptr_equ(u8* p, u8* q, u32 v)
> {u8 *result;
> u8 *pi, *qi, *ri, *re;
>
> /* where v is sizeof(type) and -1 means error */
> if(v!=sizeof(u8*)) return -1;
>
> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
> re=ri + sizeof result;
> while(ri<re)
> *ri++ = *pi++& *qi++;
> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
> while(ri<re)
> if(*ri!=*pi++ || *ri++!=*qi++)
> return 0;
> return result;
> }
>

Hmmm... 6.8.6.4p3 includes the sentence 'If the expression has a type
different from the return type of the function in which it appears, the
value is converted as if by assignment to an object having the return
type of the function." So 'return -1' would be like assigning '-1' to a
'u8*' object. Unfortunately, I believe that's a constraint violation of
6.5.16.1p1.

If 'u8' is 'uint8_t' and if 'uint8_t' is exactly the type 'unsigned
char' (it might not be), the representation should be the same as for
'void *' because 6.2.5p27 includes "A pointer to void shall have the
same representation and alignment requirements as a pointer to a
character type."

>
>> But the cast '(u32*)foo_ptr_one' is unsafe if the first member of 'struct foo'
>> is not a 'u32'; the alignment requirements can be different, for one example.
>
> ok
>
>>> {u32 *result;
>>> u8 *pi, *qi, *ri, *re;
>>>
>>> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
>>> re=ri + sizeof result;
>>> while(ri<re)
>>> *ri++ = *pi++& *qi++;
>>> pi=(u8*)&p; qi=(u8*)&q; ri=(u8*)&result;
>>> /* if( result != q ) return 0 */
>>
>> I know you've commented it out, but wish to point out that the code:
>>
>> if( result != q) return 0;
>>
>> is not safe. The object representations of two 'u32*' pointers have been
>> "merged" together with bitwise AND. But if they were unequal, the resulting
>> object representation might not be valid when interpreted as a 'u32*' pointer.
>> 'if ( result' interprets it as a 'u32*' pointer value, which might not be a
>> valid value. Fortunately, you have it commented out. :)
>
> i not understand it well
>

Let's pretend we see the object representations in memory and that they
look like:

p : DD CC BB AA : 10101010101110111100110011011101
q : EE CC BB AA : 10101010101110111100110011101110
result : CC CC BB AA : 10101010101110111100110011001100

If you use:

if( result != q)

'result' is an lvalue which "is converted to the value stored in the
designated object"[6.3.2.1p2]. "CC CC BB AA" could be a trap
representation[6.2.6.1p5] and leads to undefined behaviour. So it's a
good idea that you had it commented out. :)

>>> while(ri<re)
>>> if(*ri!=*pi++ || *ri++!=*qi++)
>>> return 0;
>>> return result;
>>> }
>>>
>>> #include<stdio.h>
>>> #include<stdlib.h>
>>>
>>> int main(void)
>>> {u32 iaa[2][2] = {{5,6},{7,8}};
>>> u32 *ip;
>>>
>>
>> Are they playing catch with the pointer star? (Just kidding. Hee hee hee.)
>>
>>> printf("iaa: {{%u,%u},{%u,%u}}\n",
>>> iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
>>> /*&iaa[0][2] ==&iaa[1][0] ?
>>> iaa[0][0], iaa[0][1], iaa[1][0], iaa[1][1]
>>> io> iaa[0]+2 == iaa[1] i see it in the debugger
>>> */
>>>
>>> ip=ptr_equ(iaa[0] + 2, iaa[1]);
>>> if(!ip){puts("Pointers have different object representation!");
>>> return EXIT_FAILURE;}
>>> puts("Pointers have the same object representation");
>>>
>>> /* Does the next line have undefined behaviour? */
>>> /* io> here not */
>>> *ip = 5;
>>> printf("iaa: {{%u,%u},{%u,%u}}\n",
>>> iaa[0][0],iaa[0][1],iaa[1][0],iaa[1][1]);
>>> return EXIT_SUCCESS;
>>> }
>>
>> Your code explicitly examines the object representations of 'u32*'-typed
>> pointers, rather than of converted-to-'void *' pointers. Ok.
>>
>> But here's a question for you: Does 'ip' point to one past the 'iaa[0]'
>
> ip here point to&(iaa[1][0]) aligned to u32 (the print say so)
>
>> array, or does it point to the first element of the 'iaa[1]' array?
>
> yes point to iaa[1] (debugger say so)
>
> ------------
> iaa: {{5,6},{7,8}}
> Pointers have the same object representation
> iaa: {{5,6},{5,8}}
> ------------
> so the element of *ip here is iaa[1][0]
>

Ok. Thanks!

io_x

6/13/2011 5:27:00 AM

0

"Shao Miller" <sha0.miller@gmail.com> ha scritto nel messaggio
news:iss38j$mii$1@dont-email.me...
> On 6/9/2011 2:00 PM, io_x wrote:
so for doing one operation for pointier a, b as a==b
you would write 14 lines with multiple instructions in them;
1) it should be easy program one machine
with one model in mind than a set of machines;
2) the result code of programming one machine can be
many times more complex than the one of set of machines
and be readable