Technical article today.
One of this year’s school projects was to design and develop an OpenGL game in C. That was the first time I was presented to OpenGL, and I was eager to use it. The project started great. The logic implied wasn’t very complicated and we were moving fast.
By the end of the project, when we were close to the deadline, a strange bug started to occur. For some reason, the game would crash at different parts of the game seemingly for no reason. That was parts of the app that had already been tested and approved. After some research I realized the crash occurred when I was trying to edit the properties of some structures.
Let me explain. The game is composed of elements. Some are shown on the screen, some are not. But all those elements, regardless of their type, are encapsulated in a standardized structure. All these standardized structures are then stores in a global array. This array wasn’t an array of pointers, the standardized structure were directly stored in it. To add to that, the array is dynamically allocated, which means I need to be *reallocated* every time a new standardized element has to be stored. For convenience, I also had stored pointers to some of the standardized element at different places. This way I was able to edit elements regardless of their places in the array.
Back to the error. The error message I was getting was « Segmentation Fault ». At first, I used ASan (Address Sanitizer) to try to locate the cause of the error. But for some reason, using ASan was preventing the error from happening, which was very weird.
After a few hours of try and guess, I decided to use Valgrind, to track memory. This time the error was happening. The message returned was something like « Accessing already free-ed memory » which was strange because I was a hundred percent sure the memory accessed at this moment wasn’t free-ed. The stack trace was showing that the error was only occurring when I tried to access a standardized element through a pointer, and not through the array. The error report was also saying that the memory had been free-ed by a realloc().
At this moment I was completely lost. I had spent two days searching for this error, and had little to no clue.
It then occurred to me, what if realloc was moving the memory? When you use a realloc, you have to get the return value both for security, and because it may have changed. It then occurred to me, what if not only the entry point, but the entire array was moved by realloc?
What was happening was that at some point when I reallocated the array, it happened to be moved to another location, changing its pointer value. But all the other pointers to elements of the array weren’t updated. Which means that they were trying to access memory that was now at another place, which causes the segmentation fault.
I just had to change the array of standardized elements to an array of pointers to the standardized elements, and the bug disappeared.
That was clearly on of the most interesting bug I ever had to debug. Even though it may have been caused by bad practices, I learned of lots of things that help me progress and understand more of how memory management is working.