Valgrind is an excellent Linux-only tool for detecting memory errors at runtime (and a lot of other stuff). For memory errors, valgrind basically checks every memory allocation, read and write to see that it's valid. This is quite an intensive process, making the program run 10 times slower or worse, but one of the nice things with Cube 2 is that it's so fast that, actually, you can run it in valgrind at a decent speed and perform actual tests. And I'm talking about the client, not the server (which can also be done, but is a much less impressive feat).
Even so, running valgrind is a time-consuming task, as it takes a lot of repeat runs to get useful results (as you fine tune the 'suppressions file', the list of warnings that it can safely ignore). This took a few days, during which the following came to light:
- Several minor issues with Cube 2 itself, including accessing uninitialized values and a mismatched new/delete. I reported them and eihrul committed appropriate fixes (which I then ported to the Intensity Engine). I am somewhat surprised none of these led to noticeable issues in practice, but I guess most compilers initialize enough stuff by default to prevent it. (Perhaps compilers should have an option to not initialize values, for testing purposes?)
- One serious issue with Cube 2, concerning bone processing in the skeletal animation system: When bones were 'unused' (not appearing in actual blend weights, etc.), that led to a read at index -1 in a C array. As with the previous issues, I reported this and eihrul committed a one-line fix.
- One minor issue with how the Intensity Engine uses Cube 2: I assumed a value was initialized by default, but it wasn't (not sure why it isn't, it somewhat goes against the conventions elsewhere, but regardless the fix was trivial).
- One serious issue with, of all things, the Intensity Engine's logging system: An incorrect reuse of a function receiving a variable number of arguments by functions passing it only one (it got confused in some cases and looked for arguments that didn't exist). The fix was trivial.
The second thing I did was finally get around to some serious testing on Windows, as during the last few months I only found time for some partial testing myself now and then, and some very useful community contributions. So, the time was right to make sure this worked, and after several hours the client was running fine (there remains an issue with the server, something minor about how linking is done, which I'll fix later on). Interestingly, as always cross-platform testing uncovered some stuff:
- The serious issue mentioned above with the Intensity Engine logging system led to actual crashes on Windows (while on Linux no errors occurred in practice). So, interestingly, this problem could have been discovered by either valgrind or by cross-platform testing.
- An issue with reading files using the C API: What I wrote worked fine on Linux, but not on Windows, apparently due to underlying platform differences. The fix was trivial, and even shortened and improved the code: To use Python's file reading system, which is already tested for cross-platform compatibility.