Crafty c questions

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Crafty c questions

Post by bob »

jwes wrote:
bob wrote:
Joost Buijs wrote:
jwes wrote:I am trying to compile crafty 25.0 with MSVC 2013 and am running into some errors.

1. This line appears in init.c

Code: Select all

memset((void *) hash_table + node * mem_per_node, 0, mem_per_node);
This looks like a bug.
I guess you have to add some parentheses like:

Code: Select all

memset((void *) (hash_table + node * mem_per_node), 0, mem_per_node);
jwes wrote: 2. This function is used if INLINEASM is not defined and does not compile:

Code: Select all

int PopCnt(uint64_t arg1) {
  int c;

  for (c = 0; x; c++)
    x &= x - 1;
  return c;
}
You have to replace arg1 by x, then it will compile.
The parens will break the above.

If you have pointer + x, then the compiler will produce code that REALLY computes "pointer + sizeof(x)" That is not what is intended above. (void *) assumes the size of an object is 1, which makes this work correctly. The parens will produce seg faults because the pointers will go way out of bounds.
MSVC gives an error on (void *):
crafty-25.0\init.c(845): error C2036: 'void *' : unknown size
I am not sure I follow here. We have compiled and run under windows with this version. It has been used by CCRL and such which was compiled by MSVC...
Joost Buijs
Posts: 1564
Joined: Thu Jul 16, 2009 10:47 am
Location: Almere, The Netherlands

Re: Crafty c questions

Post by Joost Buijs »

jwes wrote:
bob wrote:
Joost Buijs wrote:
jwes wrote:I am trying to compile crafty 25.0 with MSVC 2013 and am running into some errors.

1. This line appears in init.c

Code: Select all

memset((void *) hash_table + node * mem_per_node, 0, mem_per_node);
This looks like a bug.
I guess you have to add some parentheses like:

Code: Select all

memset((void *) (hash_table + node * mem_per_node), 0, mem_per_node);
jwes wrote: 2. This function is used if INLINEASM is not defined and does not compile:

Code: Select all

int PopCnt(uint64_t arg1) {
  int c;

  for (c = 0; x; c++)
    x &= x - 1;
  return c;
}
You have to replace arg1 by x, then it will compile.
The parens will break the above.

If you have pointer + x, then the compiler will produce code that REALLY computes "pointer + sizeof(x)" That is not what is intended above. (void *) assumes the size of an object is 1, which makes this work correctly. The parens will produce seg faults because the pointers will go way out of bounds.
MSVC gives an error on (void *):
crafty-25.0\init.c(845): error C2036: 'void *' : unknown size
This is completely understandable.
What happens is that you first convert hash_table to (void *) and then try to add (node * mem_per_node) which is illegal for C++ compilers and also for Visual C as it seems.

This is easy to solve, but without knowing the behavior of the compiler Bob is using and without looking at the rest of the source I can't tell exactly how.
You may try one of these:

Code: Select all

memset((void *) (hash_table + node * mem_per_node), 0, mem_per_node);
memset((void *) ((char *)hash_table + node * mem_per_node), 0, mem_per_node);
Cardoso
Posts: 362
Joined: Thu Mar 16, 2006 7:39 pm
Location: Portugal
Full name: Alvaro Cardoso

Re: Crafty c questions

Post by Cardoso »

In my case I just removed the "(void *)".
I used the intel compiler.

Code: Select all

memset(hash_table + node * mem_per_node, 0, mem_per_node);
...
      memset(hash_table + smp_max_threads * mem_per_node, 0,
          hash_table_size * sizeof(HASH_ENTRY) -
          mem_per_node * smp_max_threads);
...
memset(hash_path + node * mem_per_node, 0, mem_per_node);

...
memset(hash_path + smp_max_threads * mem_per_node, 0,
          hash_path_size * sizeof(HPATH_ENTRY) -
          mem_per_node * smp_max_threads);
... and so on.

regards,
Alvaro
Cardoso
Posts: 362
Joined: Thu Mar 16, 2006 7:39 pm
Location: Portugal
Full name: Alvaro Cardoso

Re: Crafty c questions

Post by Cardoso »

However I'm getting errors like:
*moveerror* start square<0 !...!
on the log window of Arena (Ctrl + F4)

And from the starting position after e2-e4, I see the arrow for the current best move, starting from A1 (rook) to c6 or f6, the destination square are right (knight moves) but the source square is wrong.



Alvaro
User avatar
cdani
Posts: 2204
Joined: Sat Jan 18, 2014 10:24 am
Location: Andorra

Re: Crafty c questions

Post by cdani »

Some time ago I compiled crafty25 in visual studio 2013:

http://www.andscacs.com/crafty/crafty25_sln.zip

It had some error I don't remember and I removed it, but I put it again because maybe it will give you ideas to solve things.
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: Crafty c questions

Post by jwes »

Cardoso wrote:In my case I just removed the "(void *)".
I used the intel compiler.

Code: Select all

memset&#40;hash_table + node * mem_per_node, 0, mem_per_node&#41;;
...
      memset&#40;hash_table + smp_max_threads * mem_per_node, 0,
          hash_table_size * sizeof&#40;HASH_ENTRY&#41; -
          mem_per_node * smp_max_threads&#41;;
...
memset&#40;hash_path + node * mem_per_node, 0, mem_per_node&#41;;

...
memset&#40;hash_path + smp_max_threads * mem_per_node, 0,
          hash_path_size * sizeof&#40;HPATH_ENTRY&#41; -
          mem_per_node * smp_max_threads&#41;;
... and so on.

regards,
Alvaro
You need to replace (void *) with (char *) or the pointer calculations will be wrong.
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: Crafty c questions

Post by jwes »

The PopCnt function in boolean.c is just wrong. this one seems to work:

Code: Select all

int PopCnt&#40;uint64_t arg1&#41; &#123;
  int c=0;

  for (; arg1; arg1 &= arg1 - 1&#41;
    c++;
  return c;
&#125;
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Crafty c questions

Post by bob »

Cardoso wrote:However I'm getting errors like:
*moveerror* start square<0 !...!
on the log window of Arena (Ctrl + F4)

And from the starting position after e2-e4, I see the arrow for the current best move, starting from A1 (rook) to c6 or f6, the destination square are right (knight moves) but the source square is wrong.



Alvaro
This is likely a result of one of those memset() calls breaking. If it copies to a bad address, it can wreck magic tables or most anything else..
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: Crafty c questions

Post by jwes »

These are the changes I had to make to get crafty to compile with MSVC.
lock.h
add

Code: Select all

#    define Pause			_mm_pause
delete

Code: Select all

void Pause&#40;) &#123;
&#125;
boolean.c
replace

Code: Select all

int PopCnt&#40;uint64_t arg1&#41; &#123;
  int c;

  for &#40;c = 0; x; c++)
    x &= x - 1;
  return c;
&#125;
with

Code: Select all

int PopCnt&#40;uint64_t arg1&#41; &#123;
  int c=0;

  for (; arg1; arg1 &= arg1 - 1&#41;
    c++;
  return c;
&#125;
epdglue.c
replace all

Code: Select all

getpid
with

Code: Select all

_getpid
init.c
replace all hash table inits

Code: Select all

memset&#40;&#40;void *)
with

Code: Select all

memset&#40;&#40;char *)
utility.c
replace all

Code: Select all

fileno
isatty
with

Code: Select all

_fileno
_isatty
I think these changes should not affect anything on other platforms.

btw, if you could separate substantive changes from more cosmetic changes, it would make diff more useful, e.g. release a version with the new print specifier, functions with changed parameter order, and reformatted comments, and a second version with new SMP, pawn eval, and pruning.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Crafty c questions

Post by bob »

jwes wrote:These are the changes I had to make to get crafty to compile with MSVC.
lock.h
add

Code: Select all

#    define Pause			_mm_pause
delete

Code: Select all

void Pause&#40;) &#123;
&#125;
boolean.c
replace

Code: Select all

int PopCnt&#40;uint64_t arg1&#41; &#123;
  int c;

  for &#40;c = 0; x; c++)
    x &= x - 1;
  return c;
&#125;
with

Code: Select all

int PopCnt&#40;uint64_t arg1&#41; &#123;
  int c=0;

  for (; arg1; arg1 &= arg1 - 1&#41;
    c++;
  return c;
&#125;
epdglue.c
replace all

Code: Select all

getpid
with

Code: Select all

_getpid
init.c
replace all hash table inits

Code: Select all

memset&#40;&#40;void *)
with

Code: Select all

memset&#40;&#40;char *)
utility.c
replace all

Code: Select all

fileno
isatty
with

Code: Select all

_fileno
_isatty
I think these changes should not affect anything on other platforms.

btw, if you could separate substantive changes from more cosmetic changes, it would make diff more useful, e.g. release a version with the new print specifier, functions with changed parameter order, and reformatted comments, and a second version with new SMP, pawn eval, and pruning.
There are some strange fixes. For example, memset().

Here is the man page for memset:

SYNOPSIS
#include <string.h>

void *
memset(void *b, int c, size_t len);


First argument is supposed to be a void pointer, not a char pointer. A char pointer produces a warning on my boxes.

getpid is another strange one. That is a library call and the compiler should add the _ to it automagically as it has been doing for MANY years. Is this a brand new version of MSVC???

Ditto for fileno and isatty() functions. Here is how fileno() is supposed to be called:

int
fileno(FILE *stream);

Adding an _ breaks the world. And for me, the compiler adds the _ to match up with the library name automatically. ALL C functions pretty much start with _. printf(), scanf(), etc... Yet we don't add "_" to them ourselves, that's the compiler's task.

The boolean.c fix for popcnt() had already been found and fixed so that 25.0 could be used by CCRL.

Can't explain what your MSVC compiler is doing, or why. But something is badly wrong somewhere since it has been compiling cleanly elsewhere. Peter Skinner compiles for windows for testing and it has been compiling just fine for him as well...