Mac 用の Robbiehanson による xmpp フレームワークを使用しています。Mac のインストゥルメント ツールでチェックしているときに、XMPPParser.m クラスでリーク (約 64 バイト) が時間とともに徐々に増加していることを確認しました。リークするコードを以下に示します。
attrNs = xmlNewNs(NULL, NULL, nodePrefix); CHECK_FOR_NULL(属性);
この問題の解決策を教えてください...
このコードを含むメソッドを参照用に以下に貼り付けます。
static void xmpp_xmlStartElement(void *ctx, const xmlChar *nodeName,
const xmlChar *nodePrefix,
const xmlChar *nodeUri,
int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int nb_defaulted,
const xmlChar **attributes)
{
NSLog(@"IN xmppStartElement");
int i, j;
xmlNsPtr lastAddedNs = NULL;
xmlParserCtxt *ctxt = (xmlParserCtxt *)ctx;
// We store the parent node in the context's node pointer.
// We keep this updated by "pushing" the node in the startElement method,
// and "popping" the node in the endElement method.
xmlNodePtr parent = ctxt->node;
// Create the node
xmlNodePtr newNode = xmlNewDocNode(ctxt->myDoc, NULL, nodeName, NULL);
CHECK_FOR_NULL(newNode);
// Add the node to the tree
if(parent == NULL)
{
// Root node
xmlAddChild((xmlNodePtr)ctxt->myDoc, newNode);
}
else
{
xmlAddChild(parent, newNode);
}
// Process the namespaces
for (i = 0, j = 0; j < nb_namespaces; j++)
{
// Extract namespace prefix and uri
const xmlChar *nsPrefix = namespaces[i++];
const xmlChar *nsUri = namespaces[i++];
// Create the namespace
xmlNsPtr newNs = xmlNewNs(NULL, nsUri, nsPrefix);
CHECK_FOR_NULL(newNs);
// Add namespace to node.
// Each node has a linked list of nodes (in the nsDef variable).
// The linked list is forward only.
// In other words, each ns has a next, but not a prev pointer.
if (newNode->nsDef == NULL)
{
newNode->nsDef = lastAddedNs = newNs;
}
else
{
lastAddedNs->next = newNs;
lastAddedNs = newNs;
}
// Is this the namespace for the node?
if (nodeUri && (nodePrefix == nsPrefix))
{
// Ex 1: node == <stream:stream xmlns:stream="url"> && newNs == stream:url
// Ex 2: node == <starttls xmlns="url"> && newNs == null:url
newNode->ns = newNs;
}
}
// Search for the node's namespace if it wasn't already found
if ((nodeUri) && (newNode->ns == NULL))
{
newNode->ns = xmpp_xmlSearchNs(ctxt->myDoc, newNode, nodePrefix);
if (newNode->ns == NULL)
{
// We use href==NULL in the case of an element creation where the namespace was not defined.
//
// We do NOT use xmlNewNs(newNode, nodeUri, nodePrefix) because that method doesn't properly add
// the namespace to BOTH nsDef and ns.
xmlNsPtr newNs = xmlNewNs(NULL, nodeUri, nodePrefix);
CHECK_FOR_NULL(newNs);
if (newNode->nsDef == NULL)
{
newNode->nsDef = lastAddedNs = newNs;
}
else
{
lastAddedNs->next = newNs;
lastAddedNs = newNs;
}
newNode->ns = newNs;
}
}
// Process all the attributes
for (i = 0, j = 0; j < nb_attributes; j++)
{
const xmlChar *attrName = attributes[i++];
const xmlChar *attrPrefix = attributes[i++];
const xmlChar *attrUri = attributes[i++];
const xmlChar *valueBegin = attributes[i++];
const xmlChar *valueEnd = attributes[i++];
// The attribute value might contain character references which need to be decoded.
//
// "Franks & Beans" -> "Franks & Beans"
xmlChar *value = xmlStringLenDecodeEntities(ctxt, // the parser context
valueBegin, // the input string
(int)(valueEnd - valueBegin), // the input string length
(XML_SUBSTITUTE_REF), // what to substitue
0, 0, 0); // end markers, 0 if none
CHECK_FOR_NULL(value);
if ((attrPrefix == NULL) && (attrUri == NULL))
{
// Normal attribute - no associated namespace
xmlAttrPtr newAttr = xmlNewProp(newNode, attrName, value);
CHECK_FOR_NULL(newAttr);
}
else
{
// Find the namespace for the attribute
xmlNsPtr attrNs = xmpp_xmlSearchNs(ctxt->myDoc, newNode, attrPrefix);
if (attrNs != NULL)
{
xmlAttrPtr newAttr = xmlNewNsProp(newNode, attrNs, attrName, value);
CHECK_FOR_NULL(newAttr);
}
else
{
**attrNs = xmlNewNs(NULL, NULL, nodePrefix);
CHECK_FOR_NULL(attrNs);**
xmlAttrPtr newAttr = xmlNewNsProp(newNode, attrNs, attrName, value);
CHECK_FOR_NULL(newAttr);
}
}
xmlFree(value);
}
// Update our parent node pointer
ctxt->node = newNode;
// Invoke delegate methods if needed
xmpp_postStartElement(ctxt);
}