How to derive from the NameTable class to mitigate XmlReader memory leak?
This article says that using XMLReader can cause string memory leak. (just search for "memory leak" to find the paragraph). It says one of the mitigations is:
One mitigation for this is to derive from the NameTable class and enforce a maximum size quota. (There is no way to prevent the use of a NameTable, or to 开发者_运维知识库switch the NameTable when it is full)
The same problem and mitigation is also mentioned here. My question is, how do I "derive from the NameTable class and enforce a maximum size quota", as the articles suggest?
I don't know if this is the only way to do that, but what is done in WCF (where you already have such a quota, MaxNameTableCharCount), is to create a subclass of System.Xml.XmlReader, and either by implementing the reader functions yourself (not fun), or by delegating to an internal reader (more likely). You can override the virtual NameTable property to return your own implementation of XmlNameTable. This implementation can simply delegate the calls to the original name table, but enforcing some quota for its size.
If the XML you need to parse conforms with the subset supported by the WCF readers (i.e., no processing instructions, no entity references, no DTDs), you can use the WCF reader directly (they can be used outside of the services). XmlDictionaryReader.CreateTextReader takes a parameter which contains the quotas to be enforced on the reader, and one of them deals exactly with the name table.
This is not the answer to your question, but it could help mitigate your "C# memory leak problem".
Using the RAII pattern for C#, you can both dispose the unmanaged resources, and (as the object goes out of scope) let the GC dipose of the managed ones.
The code I used at work is something like:
void ParseXmlString(string p_xmlString)
{
using (var stringReader = new StringReader(p_xmlString))
using (var xmlReader = XmlReader.Create(stringReader))
{
while (xmlReader.Read())
{
// etc.
}
}
}
As you can see ther, the xmlReader (and the stringReader) variable is a local one, created for each parsing attempt (*).
Meaning they will be collected (**), and thus, virtual memory leaks avoided.
Looking at the XmlReader class, I see no way to override the NameTable, so no way I see to offer an alternative implementation.
Sorry.
(*) this could not suit your project, but it suits mine, so...
(**) I hope... You never know with GC, but then, you can still try System.GC.Collect()
for that
精彩评论