binary portability between 32bit and 64 bit

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
hgm
Posts: 27796
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: binary portability between 32bit and 64 bit

Post by hgm »

Gian-Carlo Pascutto wrote:I think there is an operator precedence bug here. The cast to uintptr_t has a higher precedence than the binary addition "+ 63". Your pointer ends up outside the allocated memory because you advance it by sizeof(*uintptr_t) * 63, whereas your malloc call is in bytes.
uintptr_t is an int type, not a pointer, right? So there should be no scaling of the added constant.

If there is a problem it is that the second 63 should be written as 63UL, because otherwise the high-order 32-bits of the address will be squashed, as the extension to uintptr_t will occur after taking the complement ~,and won't involve sign extension for an unsigned type.
Gian-Carlo Pascutto
Posts: 1243
Joined: Sat Dec 13, 2008 7:00 pm

Re: binary portability between 32bit and 64 bit

Post by Gian-Carlo Pascutto »

hgm wrote: uintptr_t is an int type, not a pointer, right? So there should be no scaling of the added constant.
Ah, you're right. Confusing name :P
If there is a problem it is that the second 63 should be written as 63UL, because otherwise the high-order 32-bits of the address will be squashed, as the extension to uintptr_t will occur after taking the complement ~,and won't involve sign extension for an unsigned type.
True, but from the description the problem seems to happen with 32-bit compiles on 64-bit systems. This issue would only be a problem for 64-bit compiles.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: binary portability between 32bit and 64 bit

Post by Sven »

tpetzke wrote:Hi,

in my little chess engine I get some crash reports from testers running it on their systems. As most of them use a 64 bit system and I don't I wonder whether this can be the cause of trouble.

As the crashes seem to happen when the hash is reset I looked at my code here and ask myself if this is the proper way of coding this

Code: Select all

// enforce memory alignment to 64 byte boundary
// allocate some headroom in buffer and let the actual hash point to a 64 byte aligned address

buffer = (unsigned char *) malloc(sizeof(*hash) + 63);
hash = (THash *) (((uintptr_t) buffer + 63) & ~63);	
memset(hash,0,sizeof(*hash));

The cast to uintptr_t seems problematic. From the definition uintptr_t

"It is an unsigned int that is guaranteed to be the same size as a pointer."

but this guarantee is only valid at compile time, right ? So when compiling for a 32bit target it will be a 4byte pointer, can this cause a crash when the binary is run on a 64 bit system then ?

If so, is there a better way of coding this (a long long hack or so) or do I have to create a dedicated 32 bit (only) and a 64 bit (only) binary ?

Thanks
Thomas...
Since I suppose that resetting the hash table will not be done very often, I would add a couple of printf's that do no harm in a real game, and let the testers try again with your instrumented binary, if they are willing to help you and the crash is reproducible.

Example:

Code: Select all

printf("# prior to malloc ...\n");

buffer = (unsigned char *) malloc(sizeof(*hash) + 63);
printf("# sizeof(*hash) = %d\n", sizeof(*hash));
printf("# buffer = 0x%08x\n", buffer);

hash = (THash *) (((uintptr_t) buffer + 63) & ~63);
printf("# (uintptr_t) buffer = %d\n", (uintptr_t) buffer);
printf("# ~63 = 0x%08x\n", ~63);
printf("# (uintptr_t) ~63 = 0x%08x\n", (uintptr_t) ~63);
printf("# hash = 0x%08x\n", hash);

memset(hash,0,sizeof(*hash));
printf("# after memset.\n");
Maybe add some fflush(stdout) after each printf in case of using buffered output, to slightly increase your chances to see the last output before crashing.

Sven
mar
Posts: 2555
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: binary portability between 32bit and 64 bit

Post by mar »

I would try to play a tournament with 64-bit debug version. Then, once it crashes, a debugger will pop up, eventually showing the callstack + source code where it crashes and perhaps letting you inspect some variables if you're lucky (depends on IDE you use)... Of course that's probably of no use if those crashes don't occur in your system (or don't happen in debug version).

Martin
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: binary portability between 32bit and 64 bit

Post by Sven »

mar wrote:I would try to play a tournament with 64-bit debug version. Then, once it crashes, a debugger will pop up, eventually showing the callstack + source code where it crashes and perhaps letting you inspect some variables if you're lucky (depends on IDE you use)... Of course that's probably of no use if those crashes don't occur in your system (or don't happen in debug version).

Martin
As far as I understood the problem only occurs
- with a 32-bit build
- on a 64-bit system
- run by other testers.

Therefore I think this proposal won't work for Thomas.

Sven
mar
Posts: 2555
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: binary portability between 32bit and 64 bit

Post by mar »

Sven Schüle wrote:
mar wrote:I would try to play a tournament with 64-bit debug version. Then, once it crashes, a debugger will pop up, eventually showing the callstack + source code where it crashes and perhaps letting you inspect some variables if you're lucky (depends on IDE you use)... Of course that's probably of no use if those crashes don't occur in your system (or don't happen in debug version).

Martin
As far as I understood the problem only occurs
- with a 32-bit build
- on a 64-bit system
- run by other testers.

Therefore I think this proposal won't work for Thomas.

Sven
I've no experience with 64-bit system myself but as I understand the CPU simply switches to 32-bit mode when executing in 32-bit code, linking to 32-bit libs (or virtually linking through some legacy wrapper, that's up to OS) so there should be no problem running that on 64-bit systems (unless the OS sucks).

EDIT: It seems that you're right Sven. I thought there is a problem with 64-bit version. So I would change my proposal to "run 32-bit debug on 64-bit OS" then.

Martin