Memory Leak Fixes: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
mNo edit summary
 
(23 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=
=Shared=
==KeyValues class==
==KeyValues class==
See {{kv}}
See [[KeyValues class]]
=bin\client.dll=
=bin\client.dll=
==CPanelMetaClassMgrImp class==
==CPanelMetaClassMgrImp class==
  src\cl_dll\panelmetaclassmgr.cpp
  src\cl_dll\panelmetaclassmgr.cpp
  236a237,241
  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);
  > }
  > }
> m_MetaClassKeyValues.RemoveAll();
  }
 
=bin\server.dll=
=bin\server.dll=
==CActBusyAnimData class==
==CActBusyAnimData class==
  src\dlls\hl2_dll\ai_behavior_actbusy.cpp
  src\dlls\hl2_dll\ai_behavior_actbusy.cpp
  78a79
  124a125
CUtlVector<busyanim_t> m_ActBusyAnims;
  >       pKVAnimData->deleteThis();
> CUtlVector<const char *> m_pszSequences;
  137c138
96a98
  <      pAnim->iszSequences[BA_BUSY] = pSequence ? pSequence : NULL_STRING;
> m_pszSequences.Purge();
124a127
m_ActBusyAnims.Purge();
  > pKVAnimData->deleteThis();
  125a129,132
>inline char *CopyString( const char *in )
>{
> if ( !in )
  > return NULL;
126a134,139
> int len = Q_strlen( in );
> char *out = new char[ len + 1 ];
> Q_memcpy( out, in, len );
> out[ len ] = 0;
> return out;
>}
131a145
> char *pSequence;
136c150
< const char *pSequence = pSection->GetString( "busy_sequence", NULL );
  ---
  ---
  > m_pszSequences.AddToTail(pSequence = CopyString(pSection->GetString( "busy_sequence", NULL )));
  >       pAnim->iszSequences[BA_BUSY] = pSequence ? AllocPooledString( pSequence ) : NULL_STRING;
  138c152
  139c140
  < pSequence = pSection->GetString( "entry_sequence", NULL );
  <       pAnim->iszSequences[BA_ENTRY] = pSequence ? pSequence : NULL_STRING;
  ---
  ---
  > m_pszSequences.AddToTail(pSequence = CopyString(pSection->GetString( "entry_sequence", NULL )));
  >       pAnim->iszSequences[BA_ENTRY] = pSequence ? AllocPooledString( pSequence ) : NULL_STRING;
  140c154
  141c142
  < pSequence = pSection->GetString( "exit_sequence", NULL );
  <       pAnim->iszSequences[BA_EXIT] = pSequence ? pSequence : NULL_STRING;
  ---
  ---
  > m_pszSequences.AddToTail(pSequence = CopyString(pSection->GetString( "exit_sequence", NULL )));
  >       pAnim->iszSequences[BA_EXIT] = pSequence ? AllocPooledString( pSequence ) : NULL_STRING;
 
==RecvTable class==
{{note|I am not completely sure if this is a valid deletion... It seems right, can someone validate it by testing?}}
src\public\dt_recv.h
93a94
> delete [] m_pProps;
==CSentence class==
src\public\sentence.h
787c787
< delete m_szText;
---
> delete[] m_szText;


==WCEdit==
==WCEdit==
Line 90: Line 64:
  g_EntityClassnames = new string_t[NUM_ENT_ENTRIES];
  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=
<center><font style="line-height: 2em;font-size:2em;">&#187; See [[Compiling vgui_controls.lib]] &#171;</font></center>
<center><font style="line-height: 2em;font-size:2em;">» See [[Compiling vgui_controls.lib]] «</font></center>
==AnimationController class==
==AnimationController class==
  src\vgui2\controls\AnimationController.cpp
  src\vgui2\controls\AnimationController.cpp
Line 107: Line 146:
  > {
  > {
  > v2 = pMap->entries.Count();
  > v2 = pMap->entries.Count();
> pCur = &(pMap->entries[x]);
  > 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 121: Line 160:


==CBitmapImagePanel class==
==CBitmapImagePanel class==
  src\vgui2\controls\BitmapImagePanel.h
  src\public\vgui_controls\BitmapImagePanel.h
  21a22
  21a22
  CBitmapImagePanel( vgui::Panel *parent, char const *panelName, char const *filename = NULL );
  CBitmapImagePanel( vgui::Panel *parent, char const *panelName, char const *filename = NULL );
Line 134: Line 173:
  >}
  >}
  >
  >
  //-----------------------------------------------------------------------------
  // Purpose:
  //-----------------------------------------------------------------------------
  void CBitmapImagePanel::ComputeImagePosition(int &x, int &y, int &w, int &h)


==DirectorySelectDialog class==
==DirectorySelectDialog class==
Line 168: Line 211:
  ---
  ---
  >              _slider->DeletePanel();
  >              _slider->DeletePanel();
==SectionedListPanel class==
 
src\vgui2\controls\SectionedListPanel.cpp
 
1579a1580
= Other info and links =
m_hEditModePanel->SetVisible(false);
 
m_hEditModePanel->SetParent((Panel *)NULL);
General issues not specific to memory leaks are on the [[SDK Known Issues List]] page.
> delete m_hEditModePanel;
 
m_hEditModePanel = NULL;
[[Category:Debugging]]
[[Category:Debugging]] [[Category:Feedback]] [[Category:Programming]] [[Category:Source SDK FAQ]]
[[Category:Developer Issues and Workarounds]]
[[Category:Programming]]
[[Category:Source SDK FAQ]]

Latest revision as of 04:02, 4 January 2024

English (en)Русский (ru)Translate (Translate)

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.