question

ZoltnHegeds-7054 avatar image
0 Votes"
ZoltnHegeds-7054 asked ZoltnHegeds-7054 commented

Error remained in Visual C++ 2019 16.9.2: 32 bit pointers in 64 bit programs: reads 64 bits from memory

My English is not perfect.
Visual C++ 2019 16.9.2.
I announced an error a long time ago, I do not find this. MS wrote will be fixed in a later version. But remained:

 #include <iostream>
    
 using namespace std;
    
 int x = 1, y = 2;
 int * __ptr32 (a[2]) = {&x, &y};
 void f(int const &z) { wcout << &z << endl; }
    
 int wmain() {
  f(*(a[0]));
  int &z = *(a[0]);
  int *p = a[0];
  wcout << &z << endl << p << endl << &y << endl;
  return 0;
 }

In a 64 bit program, when a 32 bit pointer is passed to a function, as the address of a reference parameter, reads 64 bit from memory. So, the address will be bad. The program crashes if there is z instead of &z in wcout in the function f. This program requires disabled LARGE_ADDRESS_AWARE among linker's settings. This causes the program can use only 2 GB address space: 0 to 2^31-1 addresses. Debug and Release mode are concerned so. AMD64 is concerned, I have no information about ARM64.

32 bit pointers in 64 bit program useful if the program uses a lot of pointers: lists, trees, etc. This can halve memory need. 64 bit mode required to processor test/benchmark program, what must use 64 bit dlls. In 64 bit mode, there are 16 registers instead of 8, so faster. Memory comb, fill, copy, exchange, compare, arithmetic operations on big numbers has double speed than 32 bit mode.



c++
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

metablaster avatar image
0 Votes"
metablaster answered ZoltnHegeds-7054 commented

On a 32-bit system, a pointer declared with __ptr64 is truncated to a 32-bit pointer.
On a 64-bit system, a pointer declared with __ptr32 is coerced to a 64-bit pointer.

https://docs.microsoft.com/en-us/cpp/cpp/ptr32-ptr64?view=msvc-160

I don't any issue here, the documentation is clear enough that __ptr32 (32 bit pointer) will be 64 bit pointer in x64 application.

32 bit pointers in 64 bit program useful if the program uses a lot of pointers: lists, trees, etc. This can halve memory need

You may gain some memory but very far from halve the memory used, and not for free, there will be performance overhead.


· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

This is an error. In f, write to the display the value of the parameter, not the address. The program will crash. Naturally, pointers are 64 bits. If 32 bit is stored, must be zero- or sign-extended, does not extended by the next 4 bytes in the memory!

If the data structure mainly consists pointers and counters, the memory usage will be near halved. Using 32 bit pointers in 64 bit mode does not slower than in 32 bit mode, and does not slower than using 64 bit pointers. The AMD64 architecture guarantes this, ARM64 so.

0 Votes 0 ·

@ZoltnHegeds-7054

Could you please tell us where did you post the issue a long time ago? Is it on DC? Could you please provide the link and then we can help you to push the thread.


0 Votes 0 ·

I do not remember: developercommunity, technet, or other. I did not find. The title was about:

32 bit pointers in 64 bit program: reads 64 bit from memory

There was disassembly so in the error report.

0 Votes 0 ·
metablaster avatar image metablaster ZoltnHegeds-7054 ·

This is an error. In f, write to the display the value of the parameter, not the address. The program will crash.

First, please note that int x data type is 4 bytes here that is 32 bits, and since __ptr32 coerced to 64 bit pointer what you're trying to do is read 64 bits out of 32 bit value.
Secondly, this could be an error in case of dynamic storage, but variable int x from your example is allocated on the stack!
And as you know, reading stack variable out of it's assigned storage is not valid.
0 Votes 0 ·

x, y, a are global variables, not on the stack!

The error happen only at f. After the call, at z, p are correct.

 #include <iostream>
 int a[2] = {0, 1};
 f(__intt64 &z) { std::wcout << z << L'\n'; }
    
 void wmain() {
   f(a[0]);
   return 0;
 }

If you see 4294967296, the compiler is bad. The compiler does this with pointers.

0 Votes 0 ·
Show more comments