int's mixing with __int64's in argument list not working?

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

G.B. Harms
Posts: 42
Joined: Sat Aug 08, 2009 2:18 pm
Location: Almere

int's mixing with __int64's in argument list not working?

Post by G.B. Harms »

Hello,

For a long time I haven't been building a 32 bits version of my program (Bobcat), only 64 bits. Now I'm trying to build a 32 bit version again and ran into the following issue.

In my Search.h I have:

Code: Select all

protocol->postPv(search_depth/2, max_ply, node_count, nodesPerSecond(), timeUsed(), transt->getLoad(), score, pv);
Where the postPv() has signature:

Code: Select all

virtual void postPv(int depth, int max_ply, uint64 node_count, uint64 nodes_per_second, uint64 time, int hash_full, int score, const char* pv);

And the implementation just writes an UCI info command to stdout. In 64 bits compile this gives an output like:

Code: Select all

info depth 1 seldepth 1 score cp 7 hashfull 0 nodes 2 nps 2000 time 1 pv a2a3
Exactly as expected. But now, compiled for 32 bits it gives:

Code: Select all

info depth 1 seldepth 1 score cp 7 hashfull 0 nodes 2 nps 0 time 2000 pv (null)
I have debugged and can see that in 32 bits compile the values after parameter node_count are wrong upon entering the postPv() method. It looks like the alignment of the nodes_per_second parameter is 8 bytes off since it ends up in the time parameter. The uint64 is just an unsigned __int64. I have tried with all optimizations disabled, doesn't help.

Am I overlooking something obvious, or is this a compiler bug or is mixing int's with unsigned __int64's undefined? I cannot find anything about this issue on internet.

BTW. making all arguments of type uint64 solves it, but am just curious what is going on.


Gunnar
Dann Corbit
Posts: 12540
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: int's mixing with __int64's in argument list not working

Post by Dann Corbit »

Give us the printf() or std::cout line that prints out your pv, along with the data types of the arguments.
G.B. Harms
Posts: 42
Joined: Sat Aug 08, 2009 2:18 pm
Location: Almere

Re: int's mixing with __int64's in argument list not working

Post by G.B. Harms »

Dann Corbit wrote:Give us the printf() or std::cout line that prints out your pv, along with the data types of the arguments.
Hi Dan,

It is:

Code: Select all

	virtual void postPv(int depth, int max_ply, uint64 node_count, uint64 nodes_per_second, uint64 time, int hash_full, 
				int score, const char* pv) 
	{
		char buf[1024];
		snprintf(buf, sizeof(buf), "info depth %d seldepth %d score cp %d hashfull %d nodes %ld nps %ld time %ld pv %s", 
			depth, max_ply, score, hash_full, node_count, nodes_per_second, time, pv);

		output->writeLine(buf);
	}
But as I mentioned, the parameter values are already wrong upon entering the method. Each actual argument data type also matches the formal argument data type for sure.
G.B. Harms
Posts: 42
Joined: Sat Aug 08, 2009 2:18 pm
Location: Almere

Re: int's mixing with __int64's in argument list not working

Post by G.B. Harms »

G.B. Harms wrote:
Dann Corbit wrote:Give us the printf() or std::cout line that prints out your pv, along with the data types of the arguments.
Hi Dan,

It is:

Code: Select all

	virtual void postPv(int depth, int max_ply, uint64 node_count, uint64 nodes_per_second, uint64 time, int hash_full, 
				int score, const char* pv) 
	{
		char buf[1024];
		snprintf(buf, sizeof(buf), "info depth %d seldepth %d score cp %d hashfull %d nodes %ld nps %ld time %ld pv %s", 
			depth, max_ply, score, hash_full, node_count, nodes_per_second, time, pv);

		output->writeLine(buf);
	}
But as I mentioned, the parameter values are already wrong upon entering the method. Each actual argument data type also matches the formal argument data type for sure.
I can add that even when I call the postPv() with constant values for the int's and uint64's the nodes_per_second will end up in the time argument in the 32 bit build.
Dann Corbit
Posts: 12540
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: int's mixing with __int64's in argument list not working

Post by Dann Corbit »

G.B. Harms wrote:
G.B. Harms wrote:
Dann Corbit wrote:Give us the printf() or std::cout line that prints out your pv, along with the data types of the arguments.
Hi Dan,

It is:

Code: Select all

	virtual void postPv(int depth, int max_ply, uint64 node_count, uint64 nodes_per_second, uint64 time, int hash_full, 
				int score, const char* pv) 
	{
		char buf[1024];
		snprintf(buf, sizeof(buf), "info depth %d seldepth %d score cp %d hashfull %d nodes %ld nps %ld time %ld pv %s", 
			depth, max_ply, score, hash_full, node_count, nodes_per_second, time, pv);

		output->writeLine(buf);
	}
But as I mentioned, the parameter values are already wrong upon entering the method. Each actual argument data type also matches the formal argument data type for sure.
I can add that even when I call the postPv() with constant values for the int's and uint64's the nodes_per_second will end up in the time argument in the 32 bit build.
Some of the format specifiers are wrong. Unsigned long long needs %llu (or the icky MS equivalent %I64u if you are using one of the older MS compilers -- the latest MS compilers understand %llu).

Fix that first, and see what the output looks like.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: int's mixing with __int64's in argument list not working

Post by bob »

G.B. Harms wrote:Hello,

For a long time I haven't been building a 32 bits version of my program (Bobcat), only 64 bits. Now I'm trying to build a 32 bit version again and ran into the following issue.

In my Search.h I have:

Code: Select all

protocol->postPv(search_depth/2, max_ply, node_count, nodesPerSecond(), timeUsed(), transt->getLoad(), score, pv);
Where the postPv() has signature:

Code: Select all

virtual void postPv(int depth, int max_ply, uint64 node_count, uint64 nodes_per_second, uint64 time, int hash_full, int score, const char* pv);

And the implementation just writes an UCI info command to stdout. In 64 bits compile this gives an output like:

Code: Select all

info depth 1 seldepth 1 score cp 7 hashfull 0 nodes 2 nps 2000 time 1 pv a2a3
Exactly as expected. But now, compiled for 32 bits it gives:

Code: Select all

info depth 1 seldepth 1 score cp 7 hashfull 0 nodes 2 nps 0 time 2000 pv (null)
I have debugged and can see that in 32 bits compile the values after parameter node_count are wrong upon entering the postPv() method. It looks like the alignment of the nodes_per_second parameter is 8 bytes off since it ends up in the time parameter. The uint64 is just an unsigned __int64. I have tried with all optimizations disabled, doesn't help.

Am I overlooking something obvious, or is this a compiler bug or is mixing int's with unsigned __int64's undefined? I cannot find anything about this issue on internet.

BTW. making all arguments of type uint64 solves it, but am just curious what is going on.


Gunnar
Here's the question. You have a function A that calls function B passing it an int. In function B, you expect an int64. If both are in the same file when you compile them, all should be OK. But if they are compiled separately, there will certainly be a problem. It is not clear from your description what is compiled with what and what is compiled independently. Can you explain further???
Dann Corbit
Posts: 12540
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: int's mixing with __int64's in argument list not working

Post by Dann Corbit »

Is your program open source?
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: int's mixing with __int64's in argument list not working

Post by wgarvin »

Well for one thing, some of the snprintf format specifiers are wrong on 32-bit platforms... you pass __int64 parameters like node_count but give it a format specifier of %d, so 32-bit implementations of snprintf are likely to get confused there.

If you are sure the parameters are already wrong on entering the method, I would check and make sure any prototype you have for this method (in the .h file) matches exactly the parameter types in the definition of the method. Maybe one of them says int by mistake?
G.B. Harms
Posts: 42
Joined: Sat Aug 08, 2009 2:18 pm
Location: Almere

Re: int's mixing with __int64's in argument list not working

Post by G.B. Harms »

Dann Corbit wrote:
G.B. Harms wrote:
G.B. Harms wrote:
Dann Corbit wrote:Give us the printf() or std::cout line that prints out your pv, along with the data types of the arguments.
Hi Dan,

It is:

Code: Select all

	virtual void postPv(int depth, int max_ply, uint64 node_count, uint64 nodes_per_second, uint64 time, int hash_full, 
				int score, const char* pv) 
	{
		char buf[1024];
		snprintf(buf, sizeof(buf), "info depth %d seldepth %d score cp %d hashfull %d nodes %ld nps %ld time %ld pv %s", 
			depth, max_ply, score, hash_full, node_count, nodes_per_second, time, pv);

		output->writeLine(buf);
	}
But as I mentioned, the parameter values are already wrong upon entering the method. Each actual argument data type also matches the formal argument data type for sure.
I can add that even when I call the postPv() with constant values for the int's and uint64's the nodes_per_second will end up in the time argument in the 32 bit build.
Some of the format specifiers are wrong. Unsigned long long needs %llu (or the icky MS equivalent %I64u if you are using one of the older MS compilers -- the latest MS compilers understand %llu).

Fix that first, and see what the output looks like.
Yep replacing %ld with %llu solves it!

Output of 32 bit build is now:

Code: Select all

info depth 1 seldepth 1 score cp 7 hashfull 0 nodes 2 nps 2000 time 1 pv a2a3
info depth 1 seldepth 1 score cp 14 hashfull 0 nodes 2033 nps 127062 time 16 pv h2h4
info depth 1 seldepth 1 score cp 38 hashfull 0 nodes 4538 nps 283625 time 16 pv b1c3
info depth 2 seldepth 2 score cp 12 hashfull 0 nodes 7881 nps 492562 time 16 pv e2e3 g8f6
info depth 2 seldepth 2 score cp 29 hashfull 0 nodes 10668 nps 666750 time 16 pv e2e4 e7e5
info depth 3 seldepth 4 score cp 5 hashfull 0 nodes 13587 nps 438290 time 31 pv e2e4 d7d5 e4d5 d8d5
info depth 3 seldepth 4 score cp 35 hashfull 0 nodes 16755 nps 540483 time 31 pv b1c3 d7d5 e2e4
info depth 4 seldepth 8 score cp 0 hashfull 0 nodes 19811 nps 639064 time 31 pv b1c3 e7e5 e2e4 b8c6
info depth 4 seldepth 10 score cp 17 hashfull 0 nodes 22979 nps 741258 time 31 pv e2e4 d7d5 f1b5 c8d7 b5d7 d8d7
info depth 5 seldepth 11 score cp 35 hashfull 0 nodes 28068 nps 597191 time 47 pv e2e4 e7e5
info depth 6 seldepth 10 score cp 1 hashfull 0 nodes 32363 nps 688574 time 47 pv e2e4 e7e5 d2d4 e5d4 d1d4
info depth 7 seldepth 11 score cp 39 hashfull 1 nodes 44498 nps 706317 time 63 pv e2e4 e7e5 g1f3
etc.
I compile it with warning level 4 but did not get a warning when using %ld instead of %llu. Used to gcc which is very good in warnings where it comes to format specifiers :-)


Thanks!
G.B. Harms
Posts: 42
Joined: Sat Aug 08, 2009 2:18 pm
Location: Almere

Re: int's mixing with __int64's in argument list not working

Post by G.B. Harms »

bob wrote:
G.B. Harms wrote:Hello,

For a long time I haven't been building a 32 bits version of my program (Bobcat), only 64 bits. Now I'm trying to build a 32 bit version again and ran into the following issue.

In my Search.h I have:

Code: Select all

protocol->postPv(search_depth/2, max_ply, node_count, nodesPerSecond(), timeUsed(), transt->getLoad(), score, pv);
Where the postPv() has signature:

Code: Select all

virtual void postPv(int depth, int max_ply, uint64 node_count, uint64 nodes_per_second, uint64 time, int hash_full, int score, const char* pv);

And the implementation just writes an UCI info command to stdout. In 64 bits compile this gives an output like:

Code: Select all

info depth 1 seldepth 1 score cp 7 hashfull 0 nodes 2 nps 2000 time 1 pv a2a3
Exactly as expected. But now, compiled for 32 bits it gives:

Code: Select all

info depth 1 seldepth 1 score cp 7 hashfull 0 nodes 2 nps 0 time 2000 pv (null)
I have debugged and can see that in 32 bits compile the values after parameter node_count are wrong upon entering the postPv() method. It looks like the alignment of the nodes_per_second parameter is 8 bytes off since it ends up in the time parameter. The uint64 is just an unsigned __int64. I have tried with all optimizations disabled, doesn't help.

Am I overlooking something obvious, or is this a compiler bug or is mixing int's with unsigned __int64's undefined? I cannot find anything about this issue on internet.

BTW. making all arguments of type uint64 solves it, but am just curious what is going on.


Gunnar
Here's the question. You have a function A that calls function B passing it an int. In function B, you expect an int64. If both are in the same file when you compile them, all should be OK. But if they are compiled separately, there will certainly be a problem. It is not clear from your description what is compiled with what and what is compiled independently. Can you explain further???
The A is in Search.h and the B is in Protocol.h, but the actual arguments data types match the formal data types (I did not pass an int to an int64 or vice versa). I used wrong format specifiers in snprintf in B (used %ld instead of %llu) :S

Thanks!