KeyValues: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
Line 24: Line 24:


When you do that, you should get around 200 KeyValues leaks by default.
When you do that, you should get around 200 KeyValues leaks by default.
Although this modification can remove all leaked memory, it should not be relied on to take care of them.
Although this modification can remove all leaked memory, it should not be relied on to take care of them.



Revision as of 22:06, 10 January 2006

KeyValues handles input and output.

The KeyValues class can load the input from a data buffer or a file.

Important Notes

  • In tier1/KeyValues.cpp, uncomment this line to hit the ~CLeakTrack assert to see what's looking like it's leaking
// #define LEAKTRACK
  • When you have completed using a KeyValues object, make sure you always check if is is NULL and if not, call the object's deleteThis function.
  • If you fail to delete your KeyValues objects, you will end up with memory leaks.
  • It's also important to note that many instances of the usage of the KeyValues in the SDK do not call their deleteThis function, therefore making a memory leak.

CLeakTrack

This class is in tier1/KeyValues.cpp.

Replacing the deconstructor for the CLeakTrack class can help you stomp out KeyValues leaks.

	~CLeakTrack()
	{
		AssertMsg ( keys.Count() == 0, VarArgs("keys.Count() is %i",keys.Count()) );
		for(int x=0;x<keys.Count();x++)
		{
			keys[x].kv->deleteThis();
			keys.Remove(x);
		}
	}

When you do that, you should get around 200 KeyValues leaks by default.

Although this modification can remove all leaked memory, it should not be relied on to take care of them.

Example

ComboBox *pCombo = new ComboBox(...);
pCombo->AddItem("Text", new KeyValues("UserData", "Key", "Value"));

It's important to note that if you were to follow what is called by the AddItem function, you would see that the UserData KeyValues are copied, rather than using the actual input. Copying KeyValues is a common source of confusion of how your KeyValues objects are used, so make sure to follow where they go. If you are unsure, you could try calling the deleteThis function and see if the same functionality as before still exists.

Fix

ComboBox *pCombo = new ComboBox(...);
KeyValues *kv = new KeyValues("UserData", "Key", "Value");
pCombo->AddItem("Text", kv);
kv->deleteThis();

Format

The format of a data buffer or file is the following.

"SuperKey1"	"Value"
"SuperKey2"
{
	"Key1"	"Value"
	"Key2"
	{
		"SubKey1"	"Value"
		"SubKey2"
		{
			And so on...
		}
	}
}

Useful Traverses

The following loops are contained in the following function: void Traverse(KeyValues *pKV);

All Subkeys

for ( KeyValues *sub = pKV->GetFirstSubKey(); sub; sub = sub->GetNextKey() )
This loop steps through all subkeys contained in pKV.
To handle subkeys with their own subkeys in pKV, you may want use a recursive loop. To check if a subkey has subkeys, do the following:
if(sub->GetFirstSubKey())
{
	Traverse(sub);
}

All Values

for ( KeyValues *sub = pKV->GetFirstValue(); sub; sub = sub->GetNextValue() )
This loop steps through all subkeys contained in a pKV that have values.
It is also valid to use the KeyValues member function GetDataType in the loop to do a type specific traverse.