Memory Leak Fixes: Difference between revisions
		
		
		
		
		
		Jump to navigation
		Jump to search
		
				
		
» See Compiling vgui_controls.lib « 
		
	
| Thunder4ik (talk | contribs)  m (→src\lib\vgui_controls.lib: clean up) | |||
| (33 intermediate revisions by 8 users not shown) | |||
| Line 1: | Line 1: | ||
| {{lang|Memory Leak Fixes}} | |||
| On this page goes fixes for memory leaks in the SDK. | On this page goes fixes for memory leaks in the SDK. | ||
| =Shared= | |||
| ==KeyValues class== | |||
| See [[KeyValues class]] | |||
| =bin\client.dll= | =bin\client.dll= | ||
| ==CPanelMetaClassMgrImp class== | ==CPanelMetaClassMgrImp class== | ||
|   src\cl_dll\panelmetaclassmgr.cpp |   src\cl_dll\panelmetaclassmgr.cpp | ||
|   236a237, |   236a237,242 | ||
|   CPanelMetaClassMgrImp::~CPanelMetaClassMgrImp() | |||
|   { | |||
|   >	while(m_MetaClassKeyValues.Count()>0) |   >	while(m_MetaClassKeyValues.Count()>0) | ||
|   >	{ |   >	{ | ||
|   >		m_MetaClassKeyValues[0]->deleteThis(); |   >		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= | =src\lib\vgui_controls.lib= | ||
| <font style="line-height: 2em;font-size:2em;">See [[Compiling vgui_controls.lib]]</font> | <center><font style="line-height: 2em;font-size:2em;">» See [[Compiling vgui_controls.lib]] «</font></center> | ||
| ==AnimationController== | ==AnimationController class== | ||
|   src\vgui2\controls\AnimationController.cpp |   src\vgui2\controls\AnimationController.cpp | ||
|   1292a1293,1311 |   1292a1293,1311 | ||
| Line 25: | Line 146: | ||
|   >			{ |   >			{ | ||
|   >				v2 = pMap->entries.Count(); |   >				v2 = pMap->entries.Count(); | ||
|   >				for(int y=0;y<v2;y++) |   >				for(int y=0;y<v2;y++) | ||
|   >				{ |   >				{ | ||
|  >					pCur = &(pMap->entries[y]); | |||
|   >					delete [] pCur->m_pszScriptName; |   >					delete [] pCur->m_pszScriptName; | ||
|   >					delete [] pCur->m_pszVariable; |   >					delete [] pCur->m_pszVariable; | ||
| Line 38: | Line 159: | ||
|   	} |   	} | ||
| ==CBitmapImagePanel== | ==CBitmapImagePanel class== | ||
|   src\ |   src\public\vgui_controls\BitmapImagePanel.h | ||
|   21a22 |   21a22 | ||
|  	CBitmapImagePanel( vgui::Panel *parent, char const *panelName, char const *filename = NULL ); | |||
|   >	~CBitmapImagePanel(); |   >	~CBitmapImagePanel(); | ||
| Line 51: | Line 173: | ||
|   >} |   >} | ||
|   > |   > | ||
|   //----------------------------------------------------------------------------- | |||
|   // Purpose:  | |||
|   //----------------------------------------------------------------------------- | |||
|   void CBitmapImagePanel::ComputeImagePosition(int &x, int &y, int &w, int &h) | |||
| ==DirectorySelectDialog class== | ==DirectorySelectDialog class== | ||
| Line 85: | Line 211: | ||
|   --- |   --- | ||
|   >               _slider->DeletePanel(); |   >               _slider->DeletePanel(); | ||
| == | |||
| = Other info and links = | |||
| General issues not specific to memory leaks are on the [[SDK Known Issues List]] page. | |||
| [[Category:Debugging]] | |||
| [[Category:Debugging]] [[Category: | [[Category:Developer Issues and Workarounds]] | ||
| [[Category:Programming]] | |||
| [[Category:Source SDK FAQ]] | |||
Latest revision as of 04:02, 4 January 2024
On this page goes fixes for memory leaks in the SDK.
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
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.

























