Skip to content

Commit c4cfbb0

Browse files
authored
Further xmlLoadString memleak fixes (#1577)
* Clean up BuildNode * Move CXMLImpl::BuildNode to CXMLNodeImpl::BuildFromDocument() * Also free TiXmlDocuments * test destructors * fix destructors * remove test stuff
1 parent 06b6322 commit c4cfbb0

File tree

9 files changed

+66
-51
lines changed

9 files changed

+66
-51
lines changed

Client/mods/deathmatch/logic/lua/CLuaMain.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,6 @@ CLuaMain::~CLuaMain()
5757

5858
// Delete the timer manager
5959
delete m_pLuaTimerManager;
60-
61-
for (auto& xmlNode : m_XMLNodes)
62-
{
63-
delete xmlNode;
64-
}
6560

6661
CClientPerfStatLuaMemory::GetSingleton()->OnLuaMainDestroy(this);
6762
CClientPerfStatLuaTiming::GetSingleton()->OnLuaMainDestroy(this);
@@ -370,10 +365,13 @@ CXMLFile* CLuaMain::CreateXML(const char* szFilename, bool bUseIDs, bool bReadOn
370365

371366
CXMLNode* CLuaMain::ParseString(const char* strXmlContent)
372367
{
373-
CXMLNode* xmlNode = g_pCore->GetXML()->ParseString(strXmlContent);
374-
if (xmlNode)
375-
m_XMLNodes.push_back(xmlNode);
376-
return xmlNode;
368+
auto xmlStringNode = g_pCore->GetXML()->ParseString(strXmlContent);
369+
if (!xmlStringNode)
370+
return nullptr;
371+
372+
auto node = xmlStringNode->node;
373+
m_XMLStringNodes.emplace(std::move(xmlStringNode));
374+
return node;
377375
}
378376

379377
bool CLuaMain::DestroyXML(CXMLFile* pFile)

Client/mods/deathmatch/logic/lua/CLuaMain.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ class CLuaMain //: public CClient
9595

9696
class CResource* m_pResource;
9797

98-
std::list<CXMLFile*> m_XMLFiles;
99-
std::list<CXMLNode*> m_XMLNodes;
98+
std::list<CXMLFile*> m_XMLFiles;
99+
std::unordered_set<std::unique_ptr<SXMLString>> m_XMLStringNodes;
100100
static SString ms_strExpectedUndumpHash;
101101

102102
bool m_bEnableOOP;

Server/mods/deathmatch/logic/lua/CLuaMain.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,6 @@ CLuaMain::~CLuaMain()
7777
delete xmlFile;
7878
}
7979

80-
for (auto& xmlNode : m_XMLNodes)
81-
{
82-
delete xmlNode;
83-
}
84-
8580
// Eventually delete the text displays the LUA script didn't
8681
list<CTextDisplay*>::iterator iterDisplays = m_Displays.begin();
8782
for (; iterDisplays != m_Displays.end(); ++iterDisplays)
@@ -422,10 +417,13 @@ CXMLFile* CLuaMain::CreateXML(const char* szFilename, bool bUseIDs, bool bReadOn
422417

423418
CXMLNode* CLuaMain::ParseString(const char* strXmlContent)
424419
{
425-
CXMLNode* xmlNode = g_pServerInterface->GetXML()->ParseString(strXmlContent);
426-
if (xmlNode)
427-
m_XMLNodes.push_back(xmlNode);
428-
return xmlNode;
420+
auto xmlStringNode = g_pServerInterface->GetXML()->ParseString(strXmlContent);
421+
if (!xmlStringNode)
422+
return nullptr;
423+
424+
auto node = xmlStringNode->node;
425+
m_XMLStringNodes.emplace(std::move(xmlStringNode));
426+
return node;
429427
}
430428

431429
bool CLuaMain::DestroyXML(CXMLFile* pFile)

Server/mods/deathmatch/logic/lua/CLuaMain.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ class CLuaMain //: public CClient
133133
CVehicleManager* m_pVehicleManager;
134134
CMapManager* m_pMapManager;
135135

136-
list<CXMLFile*> m_XMLFiles;
137-
list<CXMLNode*> m_XMLNodes;
138-
list<CTextDisplay*> m_Displays;
139-
list<CTextItem*> m_TextItems;
136+
list<CXMLFile*> m_XMLFiles;
137+
std::unordered_set<std::unique_ptr<SXMLString>> m_XMLStringNodes;
138+
list<CTextDisplay*> m_Displays;
139+
list<CTextItem*> m_TextItems;
140140

141141
bool m_bEnableOOP;
142142

Shared/XML/CXMLImpl.cpp

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void CXMLImpl::DeleteXML(CXMLFile* pFile)
4141
delete pFile;
4242
}
4343

44-
CXMLNode* CXMLImpl::ParseString(const char* strXmlContent)
44+
std::unique_ptr<SXMLString> CXMLImpl::ParseString(const char* strXmlContent)
4545
{
4646
TiXmlDocument* xmlDoc = new TiXmlDocument();
4747
if (xmlDoc)
@@ -51,29 +51,13 @@ CXMLNode* CXMLImpl::ParseString(const char* strXmlContent)
5151
{
5252
TiXmlElement* xmlDocumentRoot = xmlDoc->RootElement();
5353
CXMLNodeImpl* xmlBaseNode = new CXMLNodeImpl(nullptr, nullptr, *xmlDocumentRoot);
54-
CXMLNode* xmlRootNode = CXMLImpl::BuildNode(xmlBaseNode, xmlDocumentRoot);
55-
return xmlRootNode;
54+
xmlBaseNode->BuildFromDocument();
55+
return std::unique_ptr<SXMLString>(new SXMLStringImpl(xmlDoc, xmlBaseNode));
5656
}
5757
}
5858
return nullptr;
5959
}
6060

61-
CXMLNode* CXMLImpl::BuildNode(CXMLNodeImpl* xmlParent, TiXmlNode* xmlNode)
62-
{
63-
TiXmlNode* xmlChild = nullptr;
64-
TiXmlElement* xmlChildElement;
65-
CXMLNodeImpl* xmlChildNode;
66-
while (xmlChild = xmlNode->IterateChildren(xmlChild))
67-
{
68-
xmlChildElement = xmlChild->ToElement();
69-
if (xmlChildElement)
70-
{
71-
xmlChildNode = new CXMLNodeImpl(nullptr, xmlParent, *xmlChildElement);
72-
CXMLImpl::BuildNode(xmlChildNode, xmlChildElement);
73-
}
74-
}
75-
return xmlParent;
76-
}
7761

7862
CXMLNode* CXMLImpl::CreateDummyNode()
7963
{

Shared/XML/CXMLImpl.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,26 @@
1313

1414
#include <xml/CXML.h>
1515

16+
typedef struct SXMLStringImpl : SXMLString
17+
{
18+
TiXmlDocument* doc;
19+
SXMLStringImpl(TiXmlDocument* d, CXMLNode* n) : doc(d) { node = n; };
20+
~SXMLStringImpl()
21+
{
22+
delete node;
23+
delete doc;
24+
};
25+
} SXMLStringImpl;
26+
1627
class CXMLImpl : public CXML
1728
{
1829
public:
1930
CXMLImpl();
2031
virtual ~CXMLImpl();
2132

22-
CXMLFile* CreateXML(const char* szFilename, bool bUseIDs, bool bReadOnly);
23-
CXMLNode* ParseString(const char* strXmlContent);
24-
CXMLNode* BuildNode(CXMLNodeImpl* xmlParent, TiXmlNode* xmlNode);
25-
void DeleteXML(CXMLFile* pFile);
33+
CXMLFile* CreateXML(const char* szFilename, bool bUseIDs, bool bReadOnly);
34+
std::unique_ptr<SXMLString> ParseString(const char* strXmlContent);
35+
void DeleteXML(CXMLFile* pFile);
2636

2737
CXMLNode* CreateDummyNode();
2838

Shared/XML/CXMLNodeImpl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ CXMLNodeImpl::~CXMLNodeImpl()
7474
}
7575
}
7676

77+
void CXMLNodeImpl::BuildFromDocument()
78+
{
79+
TiXmlNode* xmlChild = nullptr;
80+
while (xmlChild = m_pNode->IterateChildren(xmlChild))
81+
{
82+
auto xmlChildElement = xmlChild->ToElement();
83+
if (xmlChildElement)
84+
{
85+
auto xmlChildNode = new CXMLNodeImpl(nullptr, this, *xmlChildElement);
86+
xmlChildNode->BuildFromDocument();
87+
}
88+
}
89+
}
90+
7791
CXMLNode* CXMLNodeImpl::CreateSubNode(const char* szTagName, CXMLNode* pInsertAfter)
7892
{
7993
TiXmlElement* pNewNode;

Shared/XML/CXMLNodeImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ class CXMLNodeImpl : public CXMLNode
2424
CXMLNodeImpl(class CXMLFileImpl* pFile, CXMLNodeImpl* pParent, TiXmlElement& Node);
2525
~CXMLNodeImpl();
2626

27+
// BuildFromDocument recursively builds child CXMLNodeImpl from the underlying TiXmlElement.
28+
//
29+
// This is **only** used for xmlLoadString right now.
30+
// Look elsewhere if you're thinking about XML files. It does things a different way.
31+
void BuildFromDocument();
32+
2733
CXMLNode* CreateSubNode(const char* szTagName, CXMLNode* pInsertBefore = nullptr);
2834
void DeleteSubNode(CXMLNode* pNode) { delete pNode; };
2935
void DeleteAllSubNodes();

Shared/sdk/xml/CXML.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@
1414
class CXMLNode;
1515
class CXMLFile;
1616
class CXMLAttribute;
17+
typedef struct SXMLString
18+
{
19+
CXMLNode* node;
20+
virtual ~SXMLString(){};
21+
} SXMLString;
1722

1823
class CXML
1924
{
2025
public:
21-
virtual CXMLFile* CreateXML(const char* szFilename, bool bUseIDs = false, bool bReadOnly = false) = 0;
22-
virtual CXMLNode* ParseString(const char* strXmlContent) = 0;
23-
virtual void DeleteXML(CXMLFile* pFile) = 0;
24-
virtual CXMLNode* CreateDummyNode() = 0;
26+
virtual CXMLFile* CreateXML(const char* szFilename, bool bUseIDs = false, bool bReadOnly = false) = 0;
27+
virtual std::unique_ptr<SXMLString> ParseString(const char* strXmlContent) = 0;
28+
virtual void DeleteXML(CXMLFile* pFile) = 0;
29+
virtual CXMLNode* CreateDummyNode() = 0;
2530

2631
virtual CXMLAttribute* GetAttrFromID(unsigned long ulID) = 0;
2732
virtual CXMLFile* GetFileFromID(unsigned long ulID) = 0;

0 commit comments

Comments
 (0)