lairworks / nas2d-core

NAS2D is an open source, object oriented 2D game development framework written in portable C++.
http://nas2d.lairworks.com
zlib License
10 stars 5 forks source link

SDL_RWops stream leaks #786

Closed DanRStevens closed 4 years ago

DanRStevens commented 4 years ago

I believe there may be a leak of SDL_RWops objects affecting:


Many of the SDL resource handing methods take a parameter int freesrc, which is used as a boolean flag. If it is set to 1, the SDL_RWops object is automatically freed after the method is done using it, otherwise it must be manually freed.

Links to relevant documentation: TTF_OpenFontRW IMG_Load_RW Mix_LoadMUS_RW (No documentation found) Mix_LoadWAV_RW

Quote from documentation:

freesrc

  • A non-zero value means it will automatically close and free the src for you after it finishes using the src, even if a noncritical error occured.

Setting the parameter to 1 (true) allows stream creation methods to be chained, without worrying about resource leaks.

Example usage:

font=TTF_OpenFontRW(SDL_RWFromFile("font.ttf"), 1, 16);

The above pattern is used by the above mentioned objects, but the code is setting freesrc to 0. This is likely leaking the SDL_RWops objects responsible for streaming the input.

Font.cpp:

TTF_Font *font = TTF_OpenFontRW(SDL_RWFromConstMem(fontBuffer.raw_bytes(), static_cast<int>(fontBuffer.size())), 0, static_cast<int>(ptSize));

Image.cpp:

mSurface = IMG_Load_RW(SDL_RWFromConstMem(imageFile.raw_bytes(), static_cast<int>(imageFile.size())), 0);

Music.cpp:

mMusic = Mix_LoadMUS_RW(SDL_RWFromConstMem(mBuffer.raw_bytes(), static_cast<int>(mBuffer.size())), 0);

Sound.cpp:

mMixChunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(soundFile.raw_bytes(), static_cast<int>(soundFile.size())), 0);

I believe we should change the above calls to pass a freesrc value of 1. I believe that would eliminate potential leaks of the associated SDL_RWops stream objects.

Bonus if we can find a way to prove there is a memory leak, along with verifying a fix. Perhaps valgrind could come in handy for that.

ldicker83 commented 4 years ago

For Visual Studio, we can use the method presented by Microsoft here:

https://docs.microsoft.com/en-us/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2019

This is pretty straight forward and I've used a similar method in the past with great success. A sample here just loading the game and immediately exiting with the above implementation gives me this:

'OPHD.exe' (Win32): Unloaded 'C:\Windows\System32\avrt.dll' Detected memory leaks! Dumping objects -> {28378} normal block at 0x000001EEF42A3670, 11423 bytes long. Data: < p6* > FA FA FA FA FA FA FA FA 70 36 2A F4 EE 01 00 00 {27917} normal block at 0x000001EEE79F5B60, 16 bytes long. Data: <> 60 07 EF E6 EE 01 00 00 00 00 00 00 00 00 00 00 {27853} normal block at 0x000001EEF42D08A0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {27829} normal block at 0x000001EEF42DB790, 32 bytes long. Data: <fonts/opensans.t> 66 6F 6E 74 73 2F 6F 70 65 6E 73 61 6E 73 2E 74 {27828} normal block at 0x000001EEE79F1100, 16 bytes long. Data: < > 20 07 EF E6 EE 01 00 00 00 00 00 00 00 00 00 00 {27826} normal block at 0x000001EEF42DB970, 32 bytes long. Data: <fonts/opensans.t> 66 6F 6E 74 73 2F 6F 70 65 6E 73 61 6E 73 2E 74 {27825} normal block at 0x000001EEE79F0D40, 16 bytes long. Data: < > F8 06 EF E6 EE 01 00 00 00 00 00 00 00 00 00 00 {27824} normal block at 0x000001EEE6EF06D0, 176 bytes long. Data: < c> > 00 63 3E E5 EE 01 00 00 60 FE EE E6 EE 01 00 00 {27134} normal block at 0x000001EEF42D0800, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {27098} normal block at 0x000001EEF42CFB80, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {27062} normal block at 0x000001EEF42D0620, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {27026} normal block at 0x000001EEF42CFCC0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26990} normal block at 0x000001EEF42D03A0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26954} normal block at 0x000001EEF42CF7C0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26918} normal block at 0x000001EEF42CF9A0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26882} normal block at 0x000001EEF42D0260, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26846} normal block at 0x000001EEF42CF5E0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26810} normal block at 0x000001EEF42CF2C0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26774} normal block at 0x000001EEF42D0440, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26738} normal block at 0x000001EEF42CEB40, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26702} normal block at 0x000001EEF42CF180, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26666} normal block at 0x000001EEF42CFEA0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26630} normal block at 0x000001EEF42CF680, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26594} normal block at 0x000001EEF42CEC80, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26558} normal block at 0x000001EEF42CFE00, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26522} normal block at 0x000001EEF42D0940, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26486} normal block at 0x000001EEF42CF220, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26450} normal block at 0x000001EEF42D0580, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26414} normal block at 0x000001EEF42CF900, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26378} normal block at 0x000001EEF42CEFA0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26342} normal block at 0x000001EEF42B8D20, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26306} normal block at 0x000001EEF42E4930, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26270} normal block at 0x000001EEF42E3710, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26234} normal block at 0x000001EEF42E3E90, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26198} normal block at 0x000001EEF42E50B0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26162} normal block at 0x000001EEF42E35D0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26126} normal block at 0x000001EEF42E3DF0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26090} normal block at 0x000001EEF42E3530, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26054} normal block at 0x000001EEF42E3490, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {26018} normal block at 0x000001EEF42E4A70, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25982} normal block at 0x000001EEF42E3D50, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25946} normal block at 0x000001EEF42E5010, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25910} normal block at 0x000001EEF42E37B0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25874} normal block at 0x000001EEF42E41B0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25821} normal block at 0x000001EEF42E44D0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25785} normal block at 0x000001EEF42E4CF0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25749} normal block at 0x000001EEF42E38F0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25713} normal block at 0x000001EEF42E4F70, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25677} normal block at 0x000001EEF42E4390, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25641} normal block at 0x000001EEF42E3350, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25605} normal block at 0x000001EEF42E4750, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25569} normal block at 0x000001EEF42E4110, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25533} normal block at 0x000001EEF42E3A30, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25497} normal block at 0x000001EEF42E3990, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25461} normal block at 0x000001EEF42E3C10, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25425} normal block at 0x000001EEF42B8280, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25389} normal block at 0x000001EEF42B8640, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25353} normal block at 0x000001EEF42B83C0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25317} normal block at 0x000001EEF42B8320, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25281} normal block at 0x000001EEF42B81E0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25245} normal block at 0x000001EEF42B95E0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {25209} normal block at 0x000001EEF42B7EC0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {22574} normal block at 0x000001EEF42DF610, 11423 bytes long. Data: < - > FA FA FA FA FA FA FA FA 10 F6 2D F4 EE 01 00 00 {22113} normal block at 0x000001EEE79F3C70, 16 bytes long. Data: < > F0 FE EE E6 EE 01 00 00 00 00 00 00 00 00 00 00 {22049} normal block at 0x000001EEF42B9220, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {22025} normal block at 0x000001EEE798CBA0, 32 bytes long. Data: <fonts/opensans.t> 66 6F 6E 74 73 2F 6F 70 65 6E 73 61 6E 73 2E 74 {22024} normal block at 0x000001EEE79F2D20, 16 bytes long. Data: < > B0 FE EE E6 EE 01 00 00 00 00 00 00 00 00 00 00 {22022} normal block at 0x000001EEE798CEA0, 32 bytes long. Data: <fonts/opensans.t> 66 6F 6E 74 73 2F 6F 70 65 6E 73 61 6E 73 2E 74 {22021} normal block at 0x000001EEE79F39F0, 16 bytes long. Data: < > 88 FE EE E6 EE 01 00 00 00 00 00 00 00 00 00 00 {22020} normal block at 0x000001EEE6EEFE60, 176 bytes long. Data: < c> > C0 F8 EE E6 EE 01 00 00 00 63 3E E5 EE 01 00 00 {21999} normal block at 0x000001EEF42B7E20, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21963} normal block at 0x000001EEF42B8F00, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21927} normal block at 0x000001EEF42B9CC0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21891} normal block at 0x000001EEF42B9B80, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21855} normal block at 0x000001EEF42B8500, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21819} normal block at 0x000001EEF42B9180, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21783} normal block at 0x000001EEF42B9900, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21747} normal block at 0x000001EEF42B99A0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21711} normal block at 0x000001EEF42B9040, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21675} normal block at 0x000001EEF42B9720, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21639} normal block at 0x000001EEF42B8820, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21603} normal block at 0x000001EEF42B8E60, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21567} normal block at 0x000001EEF42B90E0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21531} normal block at 0x000001EEF42B97C0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21495} normal block at 0x000001EEF42B8DC0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21459} normal block at 0x000001EEF42B9360, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21423} normal block at 0x000001EEF42B92C0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21387} normal block at 0x000001EEE7A15940, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21351} normal block at 0x000001EEE7A15580, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21315} normal block at 0x000001EEE7A16340, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21279} normal block at 0x000001EEE7A15300, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21243} normal block at 0x000001EEE7A15080, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21207} normal block at 0x000001EEE7A16160, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21171} normal block at 0x000001EEE7A14FE0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21135} normal block at 0x000001EEE7A16980, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21099} normal block at 0x000001EEE7A16020, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {21063} normal block at 0x000001EEE7A156C0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {18555} normal block at 0x000001EEF426D070, 11423 bytes long. Data: < p & > FA FA FA FA FA FA FA FA 70 D0 26 F4 EE 01 00 00 {18105} normal block at 0x000001EEE79F24B0, 16 bytes long. Data:

50 F9 EE E6 EE 01 00 00 00 00 00 00 00 00 00 00 {18041} normal block at 0x000001EEE7A14CC0, 88 bytes long. Data: < k# k# > B0 6B 23 DC F8 7F 00 00 E0 6B 23 DC F8 7F 00 00 {18025} normal block at 0x000001EEE6F3F030, 56 bytes long. Data: < > A0 CE 19 DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18024} normal block at 0x000001EEE79F1BF0, 8 bytes long. Data: <> 60 CF 98 E7 EE 01 00 00 {18023} normal block at 0x000001EEE798C960, 24 bytes long. Data: < > 60 CC 98 E7 EE 01 00 00 00 00 00 00 00 00 00 00 {18022} normal block at 0x000001EEE7A16E70, 120 bytes long. Data: < > B0 F0 1B DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18021} normal block at 0x000001EEE79F18D0, 8 bytes long. Data: <> 60 CF 98 E7 EE 01 00 00 {18020} normal block at 0x000001EEE798CC60, 24 bytes long. Data: < > C0 C9 98 E7 EE 01 00 00 60 C9 98 E7 EE 01 00 00 {18019} normal block at 0x000001EEE7A17470, 120 bytes long. Data: <@ > 40 F0 1B DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18018} normal block at 0x000001EEE79F2AF0, 8 bytes long. Data: <> 60 CF 98 E7 EE 01 00 00 {18017} normal block at 0x000001EEE798C9C0, 24 bytes long. Data: < > 00 CC 98 E7 EE 01 00 00 60 CC 98 E7 EE 01 00 00 {18016} normal block at 0x000001EEE7A16DB0, 120 bytes long. Data: < > D0 EF 1B DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18015} normal block at 0x000001EEE798D020, 24 bytes long. Data: 68 C7 1B DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18014} normal block at 0x000001EEE79F1E70, 8 bytes long. Data: <> 60 CF 98 E7 EE 01 00 00 {18013} normal block at 0x000001EEE798CC00, 24 bytes long. Data: < > 00 00 00 00 00 00 00 00 C0 C9 98 E7 EE 01 00 00 {18012} normal block at 0x000001EEE7A16C30, 120 bytes long. Data: < > 90 BE 1B DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18011} normal block at 0x000001EEE6EB3460, 280 bytes long. Data: < > 98 90 1A DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18010} normal block at 0x000001EEE798CFC0, 24 bytes long. Data: < > 10 99 1A DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18009} normal block at 0x000001EEE798CF00, 24 bytes long. Data: < > C8 60 1A DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18008} normal block at 0x000001EEE6F3D5B0, 64 bytes long. Data: < B > A0 42 1A DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18007} normal block at 0x000001EEE6F3EC30, 56 bytes long. Data: <X > 60 58 1C DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18006} normal block at 0x000001EEE6F3D9B0, 64 bytes long. Data: < P > E0 50 1C DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18005} normal block at 0x000001EEE6F3D830, 56 bytes long. Data: <PO > 50 4F 1A DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18004} normal block at 0x000001EEE7957780, 104 bytes long. Data: < 1 > 80 31 1A DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18003} normal block at 0x000001EEE79570A0, 104 bytes long. Data: < > 10 FA 19 DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18002} normal block at 0x000001EEE7956910, 104 bytes long. Data: <P& > 50 26 1C DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18001} normal block at 0x000001EEE7A16F30, 128 bytes long. Data: < > B0 F4 1B DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {18000} normal block at 0x000001EEE77656B0, 72 bytes long. Data: < 4 > C8 34 19 DC F8 7F 00 00 00 BF 95 E7 EE 01 00 00 {17999} normal block at 0x000001EEE795BF00, 376 bytes long. Data: < > 60 CF 98 E7 EE 01 00 00 02 00 00 00 0A 00 00 00 {17998} normal block at 0x000001EEE798CF60, 32 bytes long. Data: < > 00 00 00 00 00 00 00 00 C0 19 0C DC F8 7F 00 00 {17989} normal block at 0x000001EEE798CD80, 32 bytes long. Data: <fonts/opensans-b> 66 6F 6E 74 73 2F 6F 70 65 6E 73 61 6E 73 2D 62 {17988} normal block at 0x000001EEE79F1A60, 16 bytes long. Data: < > 10 F9 EE E6 EE 01 00 00 00 00 00 00 00 00 00 00 {17986} normal block at 0x000001EEE798D080, 32 bytes long. Data: <fonts/opensans-b> 66 6F 6E 74 73 2F 6F 70 65 6E 73 61 6E 73 2D 62 {17985} normal block at 0x000001EEE79F2910, 16 bytes long. Data: < > E8 F8 EE E6 EE 01 00 00 00 00 00 00 00 00 00 00

There are thousands more like this. The few that I skimmed so far all look like they're pointing at font data and probably small image data.

DanRStevens commented 4 years ago

Huh, that's a pretty useful technique. Looks like quite a few memory leaks.

Is the report being generated near the end of main, or after global objects have been destructed (after the end of main)? It could be those objects haven't been destructed yet. Perhaps we could push reporting to after global objects have had a chance to be destructed. Could maybe put in a call to clear the fontCache as a quick check, or perhaps modify where the report is generated, perhaps using std::atexit.

Would be nice to get the file and line numbers of where that memory is being allocated.

ldicker83 commented 4 years ago

It's being generated at the end of main just before the function returns. This output right now is in the "Output" window but it can be redirected to a file, to another console, etc.

We could change it using the functions provided by the CRT to have it called anywhere the program exits but except for a legitimate crash it should only ever exit through one path.

DanRStevens commented 4 years ago

Ok, that might explain some of the leak reports then, since globals won't be cleaned up until after main exits, and so a report generated just before the end of main may show that memory as leaked, even though it would actually be cleaned up right after. Basically, I believe some of the reported leaks are false positives.

Admittedly, I'm a little uncertain if globals are destructed before or after atexit is called. That might still be before global destruction.

As a possible work around, we could manually clear out globals at the end of main, before the report is generated. There is already an imageCache.clear() to deal with the internal Image caching done previously. It's probably no longer required, now that internal caching has been removed, though rather than remove the call to clear(), we could add a fontCache.clear() as well for the purpose of minimizing the reported memory leaks.

DanRStevens commented 4 years ago

To add to the above, is seems even atexit called code will happen before destruction of globals. Reference: Order between destruction of global object and atexit in C++

If you want to avoid false positives for the memory leak report, then we'd probably need to manually clear global objects.

imageCache.clear();
fontCache.clear();
trackMars.release();

... maybe other objects too. Not sure if an empty global collection object will show anything in the memory leak report.