Day 105: Is it possible that turning the O2 flag in the compiler causes bugs?

Hello,

I am following along with day 105, and at this point my code is just a horrific mess. So there is definitely something I'm doing wrongly. However, when I turn on the O2 flag the program crashes and removing the flag makes it work. This is happening right after I merge the alignments into the loaded_bitmaps.

When I try to step through the code with the flag on I see that the code that adds the alignments to the bitmaps is not getting stepped into, so I believe the compiler has done something there. This scares me since so far I was thinking that I can write and check that my code works in deoptimized mode and it is guaranteed to work in the same way in optimized mode.

I have recorded a video showing the thing Im talking about:

I also zipped my code folder if someone wants to look at it, but I understand that it may be asking too much for someone to debug the code for me 😅. I'm just attaching it in case someone is curious about how I could have broken the code so badly lol

code.rar

What is most likely happening is that turning on optimization is highlighting a problem in your code that didn't trigger in debug build because in debug build memory is initialized to some value that happens to be working.

I ran your code and on my machine there isn't any error. Since this is maybe related to the assets, could you give us the assets you use ?

I used the assets from handmade hero, and the familiar doesn't display properly (I used the hero head and using the head for the player works so it loads the file properly).

hmh_familiar.png

A note on the code you gave: If you want us to help, you'd better make it easy for us to run your code. The archive you gave uses hard coded paths (in build.bat), doesn't have the folder structure needed and doesn't contain the assets. It also contains the hidden git folder and a source file named with a single quote. It's making us do extra work to try to help you, and leaves us making some guesses as to how things should be. It would have been nice if you'd taken the extra step of making the correct folder structure + assets, or modify your code to use the handmade hero assets if you can't give your assets.


Edited by Simon Anciaux on

To get things somewhat working in RemedyBG I added /DEBUG:FULL to the linker flags.

Hi Simon,

Thanks for replying. I was not expecting that someone would run the code... But in the future I will make sure to make it one step to run it.

I didn't include the assets because Im using some of the handmade hero assets and I wasn't sure if its okay to upload those on the forum where its publically accessible. However, I can upload the other assets.

I am just uploading the other assets now since you have already compiled the code. I have removed the grass0x.bmp, ground0x.bmp and tuft0x.bmp from the data folder below.

Is it okay to post the assets from the preorder bundle on the forums? If so I would make any future attachments easy to compile. If not I will just replace my assets with what is there in the bundle completely so that its easy to just drop those in. The only reason I used these assets was because I hadn't preordered until I was a little far into the series.

data.rar


Replying to mrmixer (#27012)

Ah I see! Let me try that


Replying to mrmixer (#27013)

As far as I know, you can't post the assets from handmade hero. People here often have access to them so it's easy for us to use them.

I just remembered there is a issue with the DrawBitmap function from handmade hero where it can read outside the texture because of rounding issues.

https://hero.handmade.network/forums/code-discussion/t/8202-day_39_segfault_in_drawbitmap#25475

[EDIT] This error is fixed in your code so it's not that.


Edited by Simon Anciaux on

I found the issue.

When you do PushBitmap for familiar you use the address of a loaded_bitmap that is on the stack, so when you arrive at the rendering part, that value is likely to have changed.

/* Don't do this
loaded_bitmap FamiliarBitmap = GameState->FamiliarBitmaps[0];
PushBitmap(RenderGroup, &FamiliarBitmap, v2{0, 0}, 0);
*/

/* Do this */
PushBitmap(RenderGroup, &GameState->FamiliarBitmaps[0], v2{0, 0}, 0); 

To found the issue, I removed every call to PushBitmap except for the familiar one.

I added a breakpoint in the DrawBitmap call, and saw that the Memory member wasn't properly set (0 in my case but it could be anything), other members were the correct values.

I added a data breakpoint on the GameState->FamiliarBitmaps[0].Memory just after loading the bitmaps, and that breakpoint was never triggered.

So it was clear that DrawBitmap had a copy of the loaded_bitmap struct, and that lead me to look at how PushBitmap worked and how it was called and saw the stack copy.

I think this issue could happen in debug builds too, you're just lucky that nobody modifies the stack space in that case.


Edited by Simon Anciaux on

My god you are a genius.

I see the issue you are pointing to and I will keep that in mind in the future. Its quite subtle. So basically when I do

loaded_bitmap FamiliarBitmap = GameState->FamiliarBitmaps[0];

I get the value of GameState->FamiliarBitmaps[0] copied into the varaible FamiliarBitmap on the stack. And then the reference is lost when the stack unwinds!

Is that why Casey Muratori keeps changing lines like these to

loaded_bitmap *FamiliarBitmap = GameState->FamiliarBitmaps + 0;

And actually he would have even written the first line with the amp in it like

loaded_bitmap *FamiliarBitmap = &GameState->FamiliarBitmaps[0];

I think back when I wrote this I was still not comfortable with doing the pointer math and wanted to use arrays which are closer to what I do in javascript and I definitely wasn't thinking about references vs copying.

And I guess in javascript and python type languages this kind of issue is eliminated by basically having everything be a reference all the time. And copying an object by value is the difficult thing that tricks people there instead of this where reference becomes invalid. Thus the common python .copy() example.

I will do the steps you have mentioned in how you debugged this and see if I can see the things you have mentioned seeing in the process of debugging. Thankyou so much! This is awesome!


Edited by Gaurav Gautam on
Replying to mrmixer (#27017)