What do the highlight colors and percentages in Instruments Leaks mean?

The whole snippet is:

NSDictionary *DictionaryForNode(xmlNodePtr currentNode, NSMutableDictionary *parentResult,BOOL parentContent)
{
    @autoreleasepool {
        NSMutableDictionary *resultForNode = [@{} mutableCopy];
        if (currentNode->name) {
            NSString *currentNodeContent = [NSString stringWithCString:(const char *)currentNode->name
                                                              encoding:NSUTF8StringEncoding];
            resultForNode[@"nodeName"] = currentNodeContent;
        }
        
        xmlChar *nodeContent = xmlNodeGetContent(currentNode);
        if (nodeContent != NULL) {
            NSString *currentNodeContent = [NSString stringWithCString:(const char *)nodeContent
                                                              encoding:NSUTF8StringEncoding];
            if ([resultForNode[@"nodeName"] isEqual:@"text"] && parentResult) {
                if (parentContent) {
                    NSCharacterSet *charactersToTrim = [NSCharacterSet whitespaceAndNewlineCharacterSet];
                    parentResult[@"nodeContent"] = [currentNodeContent stringByTrimmingCharactersInSet:charactersToTrim];
                    xmlFree(nodeContent);
                    return nil;
                }
                if (currentNodeContent != nil) {
                    resultForNode[@"nodeContent"] = currentNodeContent;
                }
                xmlFree(nodeContent);
                return resultForNode;
            } else {
                resultForNode[@"nodeContent"] = currentNodeContent;
            }
            xmlFree(nodeContent);
        }
        
        xmlAttr *attribute = currentNode->properties;
        if (attribute) {
            NSMutableArray *attributeArray = [@[] mutableCopy];
            while (attribute) {
                @autoreleasepool
                {
                    NSMutableDictionary *attributeDictionary = [@{} mutableCopy];
                    NSString *attributeName = [NSString stringWithCString:(const char *)attribute->name
                                                                 encoding:NSUTF8StringEncoding];
                    if (attributeName) {
                        attributeDictionary[@"attributeName"] = attributeName;
                    }
                    
                    if (attribute->children) {
                        NSDictionary *childDictionary = DictionaryForNode(attribute->children, attributeDictionary, true);
                        if (childDictionary) {
                            attributeDictionary[@"attributeContent"] = childDictionary;
                        }
                    }
                    
                    if ([attributeDictionary count] > 0) {
                        [attributeArray addObject:attributeDictionary];
                    }
                    attribute = attribute->next;
                    attributeDictionary = nil;
                }
            }
            
            if ([attributeArray count] > 0) {
                resultForNode[@"nodeAttributeArray"] = attributeArray;
            }
            attributeArray = nil;
        }
        
        xmlNodePtr childNode = currentNode->children;
        if (childNode) {
            NSMutableArray *childContentArray = [@[] mutableCopy];
            while (childNode) {
                NSDictionary *childDictionary = DictionaryForNode(childNode, resultForNode,false);
                if (childDictionary) {
                    [childContentArray addObject:childDictionary];
                }
                childNode = childNode->next;
            }
            if ([childContentArray count] > 0) {
                resultForNode[@"nodeChildArray"] = childContentArray;
            }
            childContentArray = nil;
        }
        
        xmlBufferPtr buffer = xmlBufferCreate();
        xmlNodeDump(buffer, currentNode->doc, currentNode, 0, 0);
        NSString *rawContent = [NSString stringWithCString:(const char *)buffer->content encoding:NSUTF8StringEncoding];
        if (rawContent != nil) {
            resultForNode[@"raw"] = rawContent;
        }
        xmlBufferFree(buffer);
        return resultForNode;
    }
}

And how do I debug memory leaks according to this screenshot? Thanks!

###没有找到颜色描述的文档,个人感觉无论无法释放的字节有多少,颜色都是黄色的单行背景,右上角可以按照泄露内存的比例标记


按照arc下编码方案没有看出这段代码有内存泄露。但是如果牵扯到 多线程系统调用消耗,内存可能释放就不及时了。


写了个demo测试了下,去除NSLog,去除过深的递归,ARC下显式的指针置空。Instruments多次检测没有该方法的内存泄露了。


static inline NSDictionary *DictionaryForNode(xmlNodePtr currentNode, NSMutableDictionary *parentResult,BOOL parentContent)
{
    @autoreleasepool {
        //NSMutableDictionary *resultForNode = [@{} mutableCopy];
        NSMutableDictionary *resultForNode = [NSMutableDictionary dictionary];
        if (currentNode->name) {
            NSString *currentNodeContent = [NSString stringWithCString:(const char *)currentNode->name
                                                              encoding:NSUTF8StringEncoding];
            resultForNode[@"nodeName"] = currentNodeContent;
            //0xcb
            currentNodeContent = nil;
        }
        
        xmlChar *nodeContent = xmlNodeGetContent(currentNode);
        if (nodeContent != NULL) {
            NSString *currentNodeContent = [NSString stringWithCString:(const char *)nodeContent
                                                              encoding:NSUTF8StringEncoding];
            if ([resultForNode[@"nodeName"] isEqual:@"text"] && parentResult) {
                if (parentContent) {
                    NSCharacterSet *charactersToTrim = [NSCharacterSet whitespaceAndNewlineCharacterSet];
                    parentResult[@"nodeContent"] = [currentNodeContent stringByTrimmingCharactersInSet:charactersToTrim];
                    //0xcb
                    currentNodeContent = nil;
                    charactersToTrim = nil;
                    
                    xmlFree(nodeContent);
                    return nil;
                }
                if (currentNodeContent != nil) {
                    resultForNode[@"nodeContent"] = currentNodeContent;
                }
                //0xcb
                currentNodeContent = nil;
                xmlFree(nodeContent);
                return resultForNode;
            } else {
                resultForNode[@"nodeContent"] = currentNodeContent;
            }
            //0xcb
            currentNodeContent = nil;
            xmlFree(nodeContent);
        }
        
        xmlAttr *attribute = currentNode->properties;
        if (attribute) {
            //NSMutableArray *attributeArray = [@[] mutableCopy];
            NSMutableArray *attributeArray = [NSMutableArray array];
            while (attribute) {
                @autoreleasepool
                {
                    //NSMutableDictionary *attributeDictionary = [@{} mutableCopy];
                    NSMutableDictionary *attributeDictionary = [NSMutableDictionary dictionary];
                    NSString *attributeName = [NSString stringWithCString:(const char *)attribute->name
                                                                 encoding:NSUTF8StringEncoding];
                    if (attributeName) {
                        attributeDictionary[@"attributeName"] = attributeName;
                    }
                    //0xcb
                    attributeName = nil;
                    
                    if (attribute->children) {
                        NSDictionary *childDictionary = DictionaryForNode(attribute->children, attributeDictionary, true);
                        if (childDictionary) {
                            attributeDictionary[@"attributeContent"] = childDictionary;
                        }
                        //0xcb
                        childDictionary = nil;
                    }
                    
                    if ([attributeDictionary count] > 0) {
                        [attributeArray addObject:attributeDictionary];
                    }
                    attribute = attribute->next;
                    attributeDictionary = nil;
                }
            }
            
            if ([attributeArray count] > 0) {
                resultForNode[@"nodeAttributeArray"] = attributeArray;
            }
            attributeArray = nil;
        }
        
        xmlNodePtr childNode = currentNode->children;
        if (childNode) {
            //NSMutableArray *childContentArray = [@[] mutableCopy];
            NSMutableArray *childContentArray = [NSMutableArray array];
            while (childNode) {
                NSDictionary *childDictionary = DictionaryForNode(childNode, resultForNode,false);
                if (childDictionary) {
                    [childContentArray addObject:childDictionary];
                }
                //0xcb
                childDictionary = nil;
                childNode = childNode->next;
            }
            if ([childContentArray count] > 0) {
                resultForNode[@"nodeChildArray"] = childContentArray;
            }
            childContentArray = nil;
        }
        
        xmlBufferPtr buffer = xmlBufferCreate();
        xmlNodeDump(buffer, currentNode->doc, currentNode, 0, 0);
        NSString *rawContent = [NSString stringWithCString:(const char *)buffer->content encoding:NSUTF8StringEncoding];
        if (rawContent != nil) {
            resultForNode[@"raw"] = rawContent;
        }
        //0xcb
        rawContent = nil;
        xmlBufferFree(buffer);
        return resultForNode;
    }
}

参考Demo:
GitHub

我的截图里,有绿色的高亮,就不知道是什么意思了。
这段代码截取自TFHpple,我已经在原代码的基础上改了一些了;原代码用Analysis分析就已经报泄露了:cry:

Instruments User Guide 里没有颜色的解释吗?感觉应该有。有空我找找。

发现的规律是绿色的行只有一个,其余的都是黄色的。并且从Leaks by Backtrace列表里面点击都是跳转到绿色的,猜测,绿色的行是Record检测到泄露的Frame的位置,黄色是Frame中有泄露的行,求文档斧正