I had something similar when I took over NG-Play. Rare and unmotivated crashes, every 20 games or so, but only after reducing the hash table size and converting it from heap allocation to static allocation. It took me a full weekend to fix it.
The issue went as follows: the hash tables were defined with a certain size (power of two). The bucket size was three. Now if, by accident, the bucket started close to the end AND the first entries were occupied, then the last write could happen at something like table[TABLESIZE] or so, which was out of bounds.
But that's not what made the program crash. Right after the hash table, there was another array. The array variable itself contained the address of the memory where the array content was, of course. This variable was overwritten by the out of bounds write.
Means, the array pointer of this array now was pointing into the dark. So the program crashed lateron when trying to do something with that array, which involved dereferencing the array pointer, at a totally unrelated point.
The reason why it had never been crashing in the original version was that it had been using dynamic allocation, and therefore this error had only involed a bit of heap trashing.
The solution was just to increase the table size by the bucket size.
How did I find it?
I compiled the program with -g -O0. Then I loaded it into the GNU debugger, GDB. Works under GNU/Linux as well as in Cygwin under Windows. I set a catch on the signal SIGSEGV, and GDB stopped at the line where the the crash was.
I restarted the whole thing and set both a catch on SIGSEGV and a write-catch on the corrupted array pointer variable in question. I let it run again until it stopped in the hash table function where the out of bounds access overwrote the array pointer. And then I had just to figure out why that happened.
Here are some useful links how to use GDB in command line mode:
http://www.unknownroad.com/rtfm/gdbtut/gdbsegfault.html
http://www.cprogramming.com/debugging/segfaults.html
https://sourceware.org/gdb/onlinedocs/g ... reakpoints
Another thing might be undefined behaviour, which can be really nasty. CppCheck and GCC with -Wall can detect some instances of that, but by far not all.
Solution: use the undefined behaviour sanitiser. Works under GNU/Linux only, not with Cygwin, but firing up a live distro via USB is easy enough. I used GNU/Linux Mint because it has a reasonably recent GCC.
Use the following options to compile the program:
-Wall -Wmaybe-uninitialized -Wstrict-aliasing -Wlogical-op -Wcast-align -g -fsanitize=address -fsanitize=bounds -fsanitize=object-size -fsanitize=alignment -fsanitize=null -fsanitize=undefined -fsanitize=shift -fsanitize=signed-integer-overflow -fsanitize=integer-divide-by-zero
The whole thing will be two or three times slower due to the code instrumentation. But it will print out useful feedback on the terminal, indicating what kind of problem there is in what line.
HTH.