Implemented automatic memory leak detection and reporting for CRT.

pull/28/head
sigonasr2 1 year ago
parent 67a5288984
commit 380582dfeb
  1. 14
      Crawler.sln
  2. 1
      Crawler/Attributable.h
  3. 35
      Crawler/Crawler.cpp
  4. 7
      Crawler/InventoryScrollableWindowComponent.h
  5. 21
      Crawler/Menu.cpp
  6. 1
      Crawler/Menu.h
  7. 5
      Crawler/MenuComponent.cpp
  8. 1
      Crawler/MenuComponent.h
  9. 8
      Crawler/ScrollableWindowComponent.h
  10. 2
      Crawler/Version.h
  11. 30985
      Crawler/assets/memoryleak.txt
  12. 3
      Crawler/safemap.h

@ -5,6 +5,8 @@ VisualStudioVersion = 17.5.33516.290
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Crawler", "Crawler\Crawler.vcxproj", "{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemoryLeakFileParser", "MemoryLeakFileParser\MemoryLeakFileParser.vcxproj", "{3054FF55-6C4E-4A38-89DA-E707AE2F3178}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -27,6 +29,18 @@ Global
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release|x64.Build.0 = Release|x64
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release|x86.ActiveCfg = Release|Win32
{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}.Release|x86.Build.0 = Release|Win32
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Debug|x64.ActiveCfg = Debug|x64
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Debug|x64.Build.0 = Debug|x64
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Debug|x86.ActiveCfg = Debug|Win32
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Debug|x86.Build.0 = Debug|Win32
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release Desktop|x64.ActiveCfg = Release|x64
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release Desktop|x64.Build.0 = Release|x64
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release Desktop|x86.ActiveCfg = Release|Win32
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release Desktop|x86.Build.0 = Release|Win32
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release|x64.ActiveCfg = Release|x64
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release|x64.Build.0 = Release|x64
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release|x86.ActiveCfg = Release|Win32
{3054FF55-6C4E-4A38-89DA-E707AE2F3178}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -6,6 +6,7 @@
class IAttributable{
protected:
inline virtual ~IAttributable(){};
std::map<Attribute,std::variant<VARIANTS>>attributes;
inline float&GetFloat(Attribute a){
if(attributes.count(a)==0){

@ -1551,7 +1551,32 @@ int main()
demo.Start();
}
_CrtDumpMemoryLeaks();
#ifdef _DEBUG
HANDLE hLogFile;
hLogFile = CreateFile(L"assets/memoryleak.txt", GENERIC_WRITE,
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
_CrtSetReportMode(_CRT_WARN,_CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN,hLogFile);
_CrtDumpMemoryLeaks();
CloseHandle(hLogFile);
std::ifstream file("assets/memoryleak.txt");
bool leaked=false;
while(file.good()){
std::string line;
std::getline(file,line);
if(line.find("Crawler\\")!=std::string::npos){
if(!leaked){
leaked=true;
std::cout<<std::endl<<std::endl<<std::endl<<"Memory leak detected!"<<std::endl;
}
std::cout<<line<<std::endl;
std::getline(file,line);
std::cout<<line<<std::endl;
}
}
#endif
return 0;
}
@ -1631,9 +1656,17 @@ bool Crawler::OnUserDestroy(){
delete MAP_DATA[data.first].optimizedTile;
}
}
for(auto&key:MAP_TILESETS){
delete key.second.tileset;
}
for(auto&data:GameState::states){
delete data.second;
}
delete[]pathfinder.nodes;
Menu::CleanupAllMenus();
for(auto&key:MonsterData::imgs){
delete key.second;
}
return true;
}

@ -35,7 +35,7 @@ protected:
}
}
}
void inline RemoveEmptySlots(){
inline void RemoveEmptySlots(){
//Algorithm will iterate through all slots, finding blank slots. Each time a blank slot is found, all items will shift over by one, and then the last item will be removed. Repeat until all slots iterated through.
for(int i=0;i<components.size();i++){
MenuComponent*button=components[i];
@ -58,7 +58,7 @@ protected:
}
bounds=CalculateBounds(); //Recalculate the bounds as it's possible the width/height of the component has changed.
}
virtual void OnInventorySlotsUpdate(ITCategory cat)override{
virtual inline void OnInventorySlotsUpdate(ITCategory cat)override{
std::vector<std::string>&inv=Inventory::get(cat);
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
if(components.size()<inv.size()){//We need more space to display our items.
@ -82,4 +82,7 @@ protected:
RemoveEmptySlots();
}
}
virtual inline void Cleanup()override{
}
};

@ -18,8 +18,8 @@ std::vector<MenuComponent*>Menu::unhandledComponents;
///__/////////////////////////////////////////////////////////////////////////////////////////////
//| |////////////////////////////////////////////////////////////////////////////////////////////
//| |/////WARNING! If you are adding something here you likely are adding another container with MenuComponent pointers in it right now.
//| |/////Because we are handling raw pointers, you must also add this container to the list of iterating search removal contains that occur in the
//| |/////DESTRUCTOR of MenuComponents!!!!! THIS IS NOT A DRILL!
//| |/////Because we are handling raw pointers, you must also add this container to the list of iterating search removal containers that occur in the
//| |/////DESTRUCTOR of MenuComponents!!!!! (Go to MenuComponent::~MenuComponent()) THIS IS NOT A DRILL!
//|__|////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
///__/////////////////////////////////////////////////////////////////////////////////////////////
@ -648,5 +648,18 @@ bool Menu::IsMenuOpen(){
}
void Menu::CleanupAllMenus(){
}
for(auto key:Menu::menus){
Menu*menu=key.second;
for(auto componentKey:menu->components){
MenuComponent*component=componentKey.second;
component->Cleanup();
delete component;
}
menu->components.Reset();
menu->Cleanup();
delete menu;
}
Menu::menus.clear();
}
void Menu::Cleanup(){}

@ -67,6 +67,7 @@ public:
vf2d center();
//Returns the last menu type created and last registered component, in case a component is detected as memory leaking, provides this information to each component for safety.
static std::pair<MenuType,std::string>GetMemoryLeakReportInfo();
virtual void Cleanup();
private:
Menu(vf2d pos,vf2d size);
static MenuType lastMenuTypeCreated;

@ -25,6 +25,7 @@ MenuComponent::~MenuComponent(){
std::erase_if(components,[&](MenuComponent*component){return component==this;});
}
std::erase_if(pMenu->displayComponents,[&](MenuComponent*component){return component==this;});
//pMenu->components.erase(this->name); //We're not going to do this here because we are in the middle of a loop for another menu component when cleaning up.
}
void MenuComponent::AfterCreate(){}
@ -122,4 +123,6 @@ std::string MenuComponent::GetLabel(){
void MenuComponent::Enable(bool enabled){
disabled=!enabled;
};
};
void MenuComponent::Cleanup(){}

@ -70,6 +70,7 @@ public:
virtual void OnInventorySlotsUpdate(ITCategory cat);
std::string GetLabel();
void Enable(bool enabled);
virtual void Cleanup();
};
constexpr auto operator|(ButtonAttr attribute,ButtonAttr attribute2) noexcept

@ -26,13 +26,6 @@ public:
:MenuComponent(parent,rect,"",onClick,ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD){
r.Create(rect.size.x,rect.size.y);
}
virtual inline ~ScrollableWindowComponent(){
MenuComponent::~MenuComponent();
for(MenuComponent*component:components){
delete component;
}
}
protected:
virtual inline void AfterCreate()override{
upButton=NEW MenuComponent(parentMenu,{vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y+="ThemeGlobal.MenuButtonScrollSpeed"_I;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD);
@ -192,4 +185,5 @@ public:
V(A::SCROLL_OFFSET).y+=rect.size.y/2;
return true;
};
virtual void Cleanup()override{}
};

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 1
#define VERSION_BUILD 2592
#define VERSION_BUILD 2618
#define stringify(a) stringify_(a)
#define stringify_(a) #a

File diff suppressed because it is too large Load Diff

@ -52,6 +52,9 @@ public:
size_t erase(const T&key){
return map.erase(key);
}
auto erase(std::map<T,O>::iterator it){
return map.erase(it);
}
};
//A class that has an initialization lock so that when the lock is activated, any further gets that are missing items in it will report themselves for easier debugging detection.

Loading…
Cancel
Save