Pitfalls and Lessons Part I


November 28th, 2024

Hello! Today, I won't be covering one specific feature I've created, but some of the problems I've had during development. 

SDL_Keycode vs SDL_KeyCode

Oh, this was a frustrating one. I was trying to pass an SDL_Keycode into a function but kept getting a compiler error. I have a class to determine if a key was pressed a single time or not. Here is an example call:

Here is the signature for the overridden operator:

This confused me so much. When I saw the compiler error, I just stared at the screen for fifteen minutes and felt like I was losing my mind. I can see they are the same type, so why is there a compiler error? I eventually took a look at the declaration in SDL_keycode.h and noticed this:

It seems simple now, but for the life of me, I just didn't realize there are two different types of keycodes in SDL, one with a capital "C" and one with a lowercase "c". The SDL_Keycode is a typedef for an Sint32, while SDL_KeyCode is the actual enum. What made it take even longer to realize this was that the auto-complete when I'm typing defaults to using the Sint32 version:

SDL needs to make these names more distinct, I'm embarrassed to have lost so much time on this issue…

Dynamic Casts and the VTable

I came across this issue when working on my scoring system. I'm going to have a class called ScoreCriteria, which will determine how many points the player earns when certain conditions are met. It hinges on a Notify function, which takes in a notification struct as a parameter. The base class for the notification struct doesn't need any functionality right now, I just want a common base class:

In my ScoreCriteria::Notify function, I want to try and cast the notification pointer to a child class, which will determine if extra points should be awarded. Below is the Notify function for my ScoreCriteriaTrick class, which gives the player points whenever they hit the trick button. If the player does a trick near a fallen enemy, they'll earn more points:

I wanted to do a dynamic cast for type safety and the nullptr check, but I got the following compiler error:

After some research, I realized the dynamic_cast function depends on the virtual table to check the type. Since there are no virtual functions in my SCNotificationData base class, dynamic cast won't work. To fix this, I added a virtual default destructor:

Visual Studio Memory Leak Messages

When I started this project, I enabled Visual Studio's leak detection using the CRT library. I followed the instructions from Microsoft Documentation for setup: https://learn.microsoft.com/en-us/cpp/c-runtime-library/find-memory-leaks-using-the-crt-library?view=msvc-170 Visual Studio supports more verbose memory leak messages when you #define _CRTDBG_MAP_ALLOC. Even when I added this definition, I still got vague messages. For example, I'll intentionally create a memory leak in my main file, with an int*:

I'd also like to note that I put the call to _CrtDumpMemoryLeaks after the return statement because I was getting false memory leaks for data structures that are only deleted when they go out of scope. For example, if I created a vector on the stack and called the function, a memory leak was reported. 

This produces the following output:

I did a lot of research and found a solution. You'll need to install an add-on if it isn't there already, which can be done from the Visual Studio Installer. After opening the Installer, go to your version of Visual Studio and click Modify. 

In the sidebar, underneath "Desktop development with C++", under "Optional", ensure the checkbox next to "C++ ATL for latest {version} build tools" is checked. 

The file we'll be including is atldbgmem.h. You can verify the file is there by going to the following path, assuming you're on a Windows machine:

C:\Program Files (x86)\Microsoft Visual Studio\<Year>\<Edition>\VC\Tools\MSVC\<Version>\atlmfc\include

It could be in Progam Files or Program Files (x86). Back in the main file, I'll add the #include <atldbgmem.h>. Make sure you include this file before including <crtdbg.h> and the #define:

After making these changes, the output is more verbose, showing the file and line memory is created:

This took me as long as it did because I would watch videos of people getting verbose messages while following the MSDN tutorial, but when I did the same it just wasn't working. I'd been having this problem for a while, but only recently decided to look into it more. 

Conclusion

The SDL_Keycode error and memory leak messages took me a while, so I'm glad to have figured it out. I've definitely had more pitfalls, but I felt these were the most relevant. Hopefully, you guys won't have the same issues I did!

Thanks for reading,

Jamari Shaun Williams

Leave a comment

Log in with itch.io to leave a comment.