64-bit puzzle

K

karpov2007

The computer industry is changing, and 64-bit technology is the next,
inevitable step.
Look at sample.

int main(int, const char **) {
int a = -2;
unsigned b = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (a + b); //Access violation on 64-bit platform
printf("%i\n", *ptr);
return 0;
}

Do you know why this code does not work on 64-bit system? Do you
assured, what no similar errors founds in your code? Do you know other
typical errors reduce to down state C++ code on 64-bit platforms? If
is not present then visit site www.Viva64.com.
On this site you can find plenty information, devoted to programming
of 64-bit systems. And also static analyzer Viva64 for detects
multitude 64-bit portability issues.
 
K

karpov2007

Discrepancy is admitted:
ptr = ptr + (a + b); - Invalid pointer value on 64-bit platform
printf("%i\n", *ptr); - Access violation on 64-bit platform
 
K

Kai-Uwe Bux

The computer industry is changing, and 64-bit technology is the next,
inevitable step.
Look at sample.

int main(int, const char **) {
int a = -2;
unsigned b = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (a + b); //Access violation on 64-bit platform
printf("%i\n", *ptr);
return 0;
}

Do you know why this code does not work on 64-bit system?

For the same reason it does not work on 32 bit systems: the sum a+b is
subject to the conversion rules. Since b is of unsigned type, a is
converted to unsigned type [5/9]. This is undefined behavior for negative
values of a [5/5]. If it appears to work on your platform, then it was just
by coincidence.

Do you assured, what no similar errors founds in your code?
Yes.


Do you know other
typical errors reduce to down state C++ code on 64-bit platforms?

No. However, I would surely hope that the above does not qualify as a
typical mistake. Also, it is a mistake on any platform, not just 64 bit
platforms.
If is not present then visit site www.Viva64.com.

This sentence does not parse.
On this site you can find plenty information, devoted to programming
of 64-bit systems. And also static analyzer Viva64 for detects
multitude 64-bit portability issues.

Oops, are you a spammer by any chance?


Best

Kai-Uwe Bux
 
K

Kai-Uwe Bux

Kai-Uwe Bux said:
The computer industry is changing, and 64-bit technology is the next,
inevitable step.
Look at sample.

int main(int, const char **) {
int a = -2;
unsigned b = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (a + b); //Access violation on 64-bit platform
printf("%i\n", *ptr);
return 0;
}

Do you know why this code does not work on 64-bit system?

For the same reason it does not work on 32 bit systems: the sum a+b is
subject to the conversion rules. Since b is of unsigned type, a is
converted to unsigned type [5/9]. This is undefined behavior for negative
values of a [5/5]. If it appears to work on your platform, then it was
just by coincidence.

Oops, turns out I misidentified the source of undefined behavior: a+b is not
undefined because of [4.7/2] (sometimes there are more guarantees in the
standard than I am used to expect:). So what should happen is a+b is
evaluated to unsigned(-2) + unsigned(1), which is the same as unsigned(-1).
Then this huge number is added to ptr. The undefined behavior actually
stems from [5.7/5].
 
A

Alf P. Steinbach

* Kai-Uwe Bux:
The computer industry is changing, and 64-bit technology is the next,
inevitable step.
Look at sample.

int main(int, const char **) {
int a = -2;
unsigned b = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (a + b); //Access violation on 64-bit platform
printf("%i\n", *ptr);
return 0;
}

Do you know why this code does not work on 64-bit system?

For the same reason it does not work on 32 bit systems: the sum a+b is
subject to the conversion rules. Since b is of unsigned type, a is
converted to unsigned type [5/9]. This is undefined behavior for negative
values of a [5/5].

I'd say "chapter and verse, please", except that seemingly you provided
that -- except that AFAICS the references given don't correspond to
anything in the standard.

Anyway, the signed->unsigned conversion is well-defined, §4.5/1 -> §4.7/2.

(a + b) then yields -1 + 2^n, where n is the number of value
representation bits in 'unsigned', and the rhs of the assignment ends up
with an undefined value, which yields Undefined Behavior when assigned
to 'ptr'.

If it appears to work on your platform, then it was just
by coincidence.

Yep.
 
K

Kai-Uwe Bux

Alf said:
* Kai-Uwe Bux:
The computer industry is changing, and 64-bit technology is the next,
inevitable step.
Look at sample.

int main(int, const char **) {
int a = -2;
unsigned b = 1;
int array[5] = { 1, 2, 3, 4, 5 };
int *ptr = array + 3;
ptr = ptr + (a + b); //Access violation on 64-bit platform
printf("%i\n", *ptr);
return 0;
}

Do you know why this code does not work on 64-bit system?

For the same reason it does not work on 32 bit systems: the sum a+b is
subject to the conversion rules. Since b is of unsigned type, a is
converted to unsigned type [5/9]. This is undefined behavior for negative
values of a [5/5].

I'd say "chapter and verse, please", except that seemingly you provided
that -- except that AFAICS the references given don't correspond to
anything in the standard.

They do:

[5/9]:
Many binary operators that expect operands of arithmetic or enumeration type
cause conversions and yield result types in a similar way. The purpose is
to yield a common type, which is also the type of the result. This pattern
is called the usual arithmetic conversions, which are defined as follows:
[...]
? Otherwise, if either operand is unsigned, the other shall be converted to
unsigned.

[5/5]:
If during the evaluation of an expression, the result is not mathematically
defined or not in the range of representable values for its type, the
behavior is undefined, unless such an expression is a constant expression
(5.19), in which case the program is ill-formed.


Probably the trickyness is that all of these come even before [5.1].
Anyway, the signed->unsigned conversion is well-defined, §4.5/1 -> §4.7/2.

You are correct on that one, see my self-correction elsethread.
(a + b) then yields -1 + 2^n, where n is the number of value
representation bits in 'unsigned', and the rhs of the assignment ends up
with an undefined value, which yields Undefined Behavior when assigned
to 'ptr'.

True, I also realized that afterwards.



Thanks

Kai-Uwe Bux
 
P

Pan

ptr = ptr + (a + b); //Access violation on 64-bit platform
printf("%i\n", *ptr);

I found the same problem on the code I'm working on.
It's because (a+b) is unsigned and usually they're still 32 bits wide,
but the pointers are 64 bits wide. You're actually ADDING a big
(>4billions) number rather than subtracting a small amount.
This worked just by coincidence on most older architectures because
pointers and unsigned were the same bits wide (they're usually both 32).
 

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

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,044
Latest member
RonaldNen

Latest Threads

Top