【问题标题】:Memory leak in xmpp framework by RobbiehansonRobbiehanson 在 xmpp 框架中的内存泄漏
【发布时间】:2013-03-30 08:04:57
【问题描述】:

我一直在为 mac 使用 Robbiehanson 的 xmpp 框架。同时检查仪器 mac 中的工具,我观察到 XMPPParser.m 类中的泄漏(大约 64 个字节)随着时间逐渐增加。泄漏的代码如下。

attrNs = xmlNewNs(NULL, NULL, nodePrefix); CHECK_FOR_NULL(attrNs);

请提供此问题的解决方案...

包含此代码的方法粘贴在下面以供参考:

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 &#38; 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);

}

【问题讨论】:

  • 你试过@autoreleasepool。它会在一定程度上管理泄漏吗? sdk 本身是否包含泄漏?
  • 这段代码是c语言的。所以不能使用@autoreleasepool。据我所知,代码sn-p, attrNs = xmlNewNs(NULL, NULL, nodePrefix);导致泄漏。其内存已分配且从未释放。

标签: objective-c c xmppframework


【解决方案1】:

尝试在最后一个CHECK_FOR_NULL(newAttr); 下方添加xmlFreeNs(attrNs);

【讨论】:

  • 我试过添加 xmlFreeNs(attrNs);但是应用程序崩溃了,任何适当的答案都会有所帮助。
猜你喜欢
  • 2011-05-29
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-20
  • 1970-01-01
相关资源
最近更新 更多