Memory Leak Fixes

On this page goes fixes for memory leaks in the SDK.
=Shared=
==KeyValues class==
See KeyValues class
=bin\client.dll=
==CPanelMetaClassMgrImp class==
 src\cl_dll\panelmetaclassmgr.cpp
 236a237,242
 CPanelMetaClassMgrImp::~CPanelMetaClassMgrImp()
 {
 >	while(m_MetaClassKeyValues.Count()>0)
 >	{
 >		if(m_MetaClassKeyValues[0])
 >			m_MetaClassKeyValues[0]->deleteThis();
 >		m_MetaClassKeyValues.RemoveAt(0);
 >	}
 }
=bin\server.dll=
==CActBusyAnimData class==
 src\dlls\hl2_dll\ai_behavior_actbusy.cpp
 124a125
 > pKVAnimData->deleteThis();
 137c138
 < pAnim->iszSequences[BA_BUSY] = pSequence ? pSequence : NULL_STRING;
 ---
 > pAnim->iszSequences[BA_BUSY] = pSequence ? AllocPooledString( pSequence ) : NULL_STRING;
 139c140
 < pAnim->iszSequences[BA_ENTRY] = pSequence ? pSequence : NULL_STRING;
 ---
 > pAnim->iszSequences[BA_ENTRY] = pSequence ? AllocPooledString( pSequence ) : NULL_STRING;
 141c142
 < pAnim->iszSequences[BA_EXIT] = pSequence ? pSequence : NULL_STRING;
 ---
 > pAnim->iszSequences[BA_EXIT] = pSequence ? AllocPooledString( pSequence ) : NULL_STRING;
==WCEdit==
 src\dlls\wcedit.cpp
 449a450,460
 Vector *g_EntityPositions = NULL;
 QAngle *g_EntityOrientations = NULL;
 string_t *g_EntityClassnames = NULL;
 
 >class GlobalCleanUp : public CAutoGameSystem
 >{
 >	void Shutdown()
 >	{
 >		delete [] g_EntityPositions;
 >		delete [] g_EntityOrientations;
 >		delete [] g_EntityClassnames;
 >		delete this;
 >	}
 >};
 >
 
 459a471
 	if ( !g_EntityPositions )
 	{
 >		new GlobalCleanUp();
 		g_EntityPositions = new Vector[NUM_ENT_ENTRIES];
 		g_EntityOrientations = new QAngle[NUM_ENT_ENTRIES];
 		// have to save these too because some entities change the classname on spawn (e.g. prop_physics_override, physics_prop)
 		g_EntityClassnames = new string_t[NUM_ENT_ENTRIES];
 	}
==Player Names==
Allocated names don't get freed until LevelShutdownPostEntity.
This issue arises because of the usage of pooled strings for saving names to memory. When a name change is made, rather than deleting the old name, it just changes the netname string_t to a newly allocated string.
===hl2mp_client.cpp===
 void ClientPutInServer( edict_t *pEdict, const char *playername )
 {
 	// Allocate a CBaseTFPlayer for pev, and call spawn
 	CHL2MP_Player *pPlayer = CHL2MP_Player::CreatePlayer( "player", pEdict );
 
 	char trimmedName[MAX_PLAYER_NAME_LENGTH];
 	Q_strncpy( trimmedName, playername, sizeof( trimmedName ) );
 -	pPlayer->PlayerData()->netname = AllocPooledName( trimmedName );
 +	pPlayer->PlayerData()->netname = MAKE_STRING(strdup( trimmedName ));
 }
===teamplay_gamerules.cpp===
 	const char * name = engine->GetClientConVarValue( pPlayer->entindex(), "name" );
 
 	// msg everyone if someone changes their name, and it isn't the first time (changing no name to current name)
 	// Note, not using FStrEq so that this is case sensitive
 	if ( pPlayer->pl.netname != NULL_STRING && 
 		 STRING(pPlayer->pl.netname)[0] != 0 && 
 		 Q_strcmp( STRING(pPlayer->pl.netname), name ) )
 	{
 		IGameEvent * event = gameeventmanager->CreateEvent( "player_changename" );
 		if ( event )
 		{
 			event->SetInt( "userid", pPlayer->GetUserID() );
 			event->SetString( "oldname", STRING(pPlayer->pl.netname) );
 			event->SetString( "newname", name );
 			gameeventmanager->FireEvent( event );
 		}
 		
 		delete STRING(pPlayer->pl.netname);
 -		pPlayer->pl.netname = AllocPooledString( name );
 +		pPlayer->pl.netname = MAKE_STRING(strdup( name ));
 	}
===player.cpp===
 CBasePlayer::~CBasePlayer( )
 {
 	VPhysicsDestroyObject();
 +	delete STRING(pl.netname);
 }
== CCommentarySystem class ==
 src\dlls\CommentarySystem.cpp
 [ In InitCommentary() method. 
 Immediately after the if ( pkvFile->LoadFromFile( filesystem, szFullName, "MOD" ) ) block ]
 491a492
 > 		pkvFile->deleteThis();
== CDevShotSystem class ==
 src\dlls\point_devshot_camera.cpp
 [ In FrameUpdatePostEntityThink() method. 
 Immediately after the if ( pkvMapCameras->LoadFromFile( filesystem, szFullName, "MOD" ) ) block ]
 242a243
 > 			pkvMapCameras->deleteThis();
== CBasePropDoor class ==
 src\dlls\props.cpp
 [ In CalcDoorSounds() method.
 Immediately after the if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) block ]
 3230a3231
 > 	modelKeyValues->deleteThis();
=src\lib\vgui_controls.lib=
» See Compiling vgui_controls.lib «
==AnimationController class==
 src\vgui2\controls\AnimationController.cpp
 1292a1293,1311
 	~CPanelAnimationDictionary()
 	{
 >		int v2, v1 = m_AnimationMaps.Count();
 >		PanelAnimationMapEntry *pCur;
 >		PanelAnimationMap *pMap;
 >		for(int x=0;x<v1;x++)
 >		{
 >			pMap = m_AnimationMaps[x].map;
 >			if(pMap)
 >			{
 >				v2 = pMap->entries.Count();
 >				for(int y=0;y<v2;y++)
 >				{
 >					pCur = &(pMap->entries[y]);
 >					delete [] pCur->m_pszScriptName;
 >					delete [] pCur->m_pszVariable;
 >					delete [] pCur->m_pszType;
 >					delete [] pCur->m_pszDefaultValue;
 >				}
 >			}
 >		}
 		m_PanelAnimationMapPool.Clear();
 	}
==CBitmapImagePanel class==
 src\public\vgui_controls\BitmapImagePanel.h
 21a22
 	CBitmapImagePanel( vgui::Panel *parent, char const *panelName, char const *filename = NULL );
 >	~CBitmapImagePanel();
 src\vgui2\controls\BitmapImagePanel.cpp
 61a62,67
 >CBitmapImagePanel::~CBitmapImagePanel()
 >{
 >	delete [] m_pszImageName;
 >	delete [] m_pszColorName;
 >}
 >
 //-----------------------------------------------------------------------------
 // Purpose: 
 //-----------------------------------------------------------------------------
 void CBitmapImagePanel::ComputeImagePosition(int &x, int &y, int &w, int &h)
==DirectorySelectDialog class==
 src\vgui2\controls\DirectorySelectDialog.cpp
 258c258,260
 <	int rootIndex = m_pDirTree->AddItem(new KeyValues("root", "Text", m_szCurrentDrive), -1);
 ---
 >	KeyValues *kv = new KeyValues("root", "Text", m_szCurrentDrive);
 >	int rootIndex = m_pDirTree->AddItem(kv, -1);
 >	kv->deleteThis();
 294a297
 				m_pDirTree->AddItem(kv, parentNodeIndex);
 >				kv->deleteThis();
 			}
 410a414
 			int itemID = m_pDirTree->AddItem(kv, selectedIndex);
 >			kv->deleteThis();
==FileOpenDialog class==
 src\vgui2\controls\FileOpenDialog.cpp
 506a507
 	int itemID = m_pFileTypeCombo->AddItem(filterName, kv);
 >	kv->deleteThis();
 	if ( bActive )
==ScrollBar class==
 src\vgui2\controls\ScrollBar.cpp
 323c323
 < _button[index]->SetParent((Panel *)NULL);
 ---
 > _button[index]->DeletePanel();
 351c351
 < _slider->SetParent((Panel *)NULL);
 ---
 > _slider->DeletePanel();
= Other info and links =
General issues not specific to memory leaks are on the SDK Known Issues List page.
Category:Debugging
Category:Developer Issues and Workarounds
Category:Programming
Category:Source SDK FAQ