2016-12-08 21 views
0

私は、要素を反復処理することによってxmlファイルを解析しようとしています。xmlStrndupのValgrindメモリリーク

これを行うための基本的な方法は次のとおりです。しかし、私はこのメソッドが呼び出されるたびにリークを観察しています。

コード:以下のように

std::string getUrl(std::vector<std::string> keyPath, std::string element, std::string fName) 
{ 

    xmlDocPtr m_doc; 
    xmlNodePtr m_cur; 
    std::string m_fileName; 
    bool isEmpty; 
    int i=0; 
    std::string value = ""; 
    isEmpty = false; 
    m_fileName = fName; 
    struct stat stat_buf; 
    int rc = stat(m_fileName.c_str(), &stat_buf); 
    if(rc==0) 
    { 
     m_doc = xmlParseFile(m_fileName.c_str()); 
    } 
    else 
    { 
     isEmpty = true; 
    } 

    if(isEmpty) 
    { 
     value = "Empty file found"; 
     xmlFreeDoc(m_doc); 
     xmlCleanupCharEncodingHandlers(); 
     xmlCleanupParser(); 
     return value; 
    } 
    if(m_doc != NULL) 
    { 
     m_cur = xmlDocGetRootElement(m_doc); 
    } 
    if(m_cur != NULL) 
    { 
     if(!xmlStrcmp(m_cur->name, (const xmlChar *)(keyPath.at(i).c_str()))) 
     { 
      m_cur = m_cur->xmlChildrenNode; 
      ++i; 
     } 
     else 
     { 
      value = "root element not found"; 
      return value; 
     } 
     while(m_cur != NULL) 
     { 
      if (!xmlStrcmp (m_cur -> name, (const xmlChar *) keyPath.at(i).c_str())) 
      { 
       m_cur = m_cur->xmlChildrenNode; 
       i++; 
      } 
      m_cur = m_cur -> next; 
      if (!xmlStrcmp (m_cur -> name, (const xmlChar *) keyPath.back().c_str())) 
      { 
       m_cur = m_cur->xmlChildrenNode; 
       break; 
      } 
     } 
     while (m_cur != NULL) 
     { 
     if (!xmlStrcmp (m_cur -> name, (const xmlChar *) element.c_str())) 
     { 
      if(xmlNodeGetContent(m_cur->xmlChildrenNode) != NULL) 
      value = (char*)(xmlNodeGetContent(m_cur->xmlChildrenNode)); 
      else 
      value = ""; 
     } 
     m_cur = m_cur -> next; 
     } 
    } 

    //call the necessary cleanup APIs of libxml2 to free the dynamically allocated memory 
    xmlFreeDoc(m_doc); 
    xmlCleanupCharEncodingHandlers(); 
    xmlCleanupParser(); 

    if(!value.empty()) 
    { 
     return value; 
    } 
    else 
    { 
     value = "value not found"; 
     return value; 
    } 
} 

Valgrindのリークがある:

==1598== 
==1598== HEAP SUMMARY: 
==1598==  in use at exit: 139,402 bytes in 1,053 blocks 
==1598== total heap usage: 1,222 allocs, 169 frees, 284,997 bytes allocated 
==1598== 
==1598== 28 bytes in 1 blocks are definitely lost in loss record 29 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x526D928: xmlStrndup (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x40198D: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401BAE: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402A56: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 28 bytes in 1 blocks are definitely lost in loss record 30 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x526D928: xmlStrndup (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x4019A4: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401BAE: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402A56: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 30 bytes in 1 blocks are definitely lost in loss record 31 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x526D928: xmlStrndup (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x40198D: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401BAE: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402CD2: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 30 bytes in 1 blocks are definitely lost in loss record 32 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x526D928: xmlStrndup (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x4019A4: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401BAE: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402CD2: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 30 bytes in 1 blocks are definitely lost in loss record 33 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x526D928: xmlStrndup (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x40198D: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401FF4: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402F30: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 30 bytes in 1 blocks are definitely lost in loss record 34 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x526D928: xmlStrndup (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x4019A4: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401FF4: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402F30: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 21,852 (176 direct, 21,676 indirect) bytes in 1 blocks are definitely lost in loss record 77 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x5215324: xmlNewDoc (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x52C01B8: xmlSAX2StartDocument (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x520E25D: xmlParseDocument (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x520E561: xmlSAXParseFileWithData (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x40181A: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401BAE: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402A56: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 21,852 (176 direct, 21,676 indirect) bytes in 1 blocks are definitely lost in loss record 78 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x5215324: xmlNewDoc (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x52C01B8: xmlSAX2StartDocument (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x520E25D: xmlParseDocument (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x520E561: xmlSAXParseFileWithData (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x40181A: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401BAE: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402CD2: main (in /cluster/home/XmlParser) 
==1598== 
==1598== 21,852 (176 direct, 21,676 indirect) bytes in 1 blocks are definitely lost in loss record 79 of 80 
==1598== at 0x4C2A6FE: malloc (vg_replace_malloc.c:296) 
==1598== by 0x5215324: xmlNewDoc (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x52C01B8: xmlSAX2StartDocument (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x520E25D: xmlParseDocument (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x520E561: xmlSAXParseFileWithData (in /usr/lib64/libxml2.so.2.9.1) 
==1598== by 0x40181A: getUrl(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x401FF4: parseXmlFile(std::vector<std::string, std::allocator<std::string> >, std::string, std::string) (in /cluster/home/XmlParser) 
==1598== by 0x402F30: main (in /cluster/home/XmlParser) 
==1598== 
==1598== LEAK SUMMARY: 
==1598== definitely lost: 704 bytes in 9 blocks 
==1598== indirectly lost: 65,028 bytes in 1,023 blocks 
==1598==  possibly lost: 0 bytes in 0 blocks 
==1598== still reachable: 73,670 bytes in 21 blocks 
==1598==   suppressed: 0 bytes in 0 blocks 
==1598== Reachable blocks (those to which a pointer was found) are not shown. 
==1598== To see them, rerun with: --leak-check=full --show-leak-kinds=all 
==1598== 
==1598== For counts of detected and suppressed errors, rerun with: -v 
==1598== ERROR SUMMARY: 9 errors from 9 contexts (suppressed: 0 from 0) 

あなたが私に実際に漏れの原因になっている事を助けることができれば、私はそれを本当に感謝します。おかげで事前

+0

最適化せずにコンパイルして完全なデバッグを有効にしてください。そして、valgrindは問題がどこにあるかを教えてくれます。 – Jonas

+0

これを普通にコンパイルすると、上記のvalgrind出力が得られます。まだ何が問題なのかよくわからない – AbhinayB

答えて

1

にコードのこの作品は、2つのメモリリークが発生します。

if(xmlNodeGetContent(m_cur->xmlChildrenNode) != NULL) 
    value = (char*)(xmlNodeGetContent(m_cur->xmlChildrenNode)); 
else 
    value = ""; 

xmlNodeGetContentxmlFreeで解放されなければならない文字列を返します。コードは次のようになります。

xmlChar *content = xmlNodeGetContent(m_cur->xmlChildrenNode); 
if (content != NULL) { 
    value = (char*)content; 
    xmlFree(content); 
} 
else { 
    value = ""; 
} 

また、xmlDocがリークすることがあります。これは、ドキュメントを解放しない "ルート要素が見つかりません"リターンパスによって発生する可能性があります。

0

今、nwellnhofから、あなたの質問に対する回答が漏れている場所が示されています。

私はそれらを修正する方法を教えようとします。未テストのコードに注意してください。

std::unique_ptrをscope_guardとして使用しています(誤っている)。

まず、generel get stringメソッドを作成します。これは、文字列の問題を解決します。

std::string xmlGetString(xmlNodePtr m_cur) { 
    std::unique_ptr<xmlChar> 
    content(xmlNodeGetContent(m_cur->xmlChildrenNode), xmlFree); // 1 

    if (content != NULL) { 
    return (char*)content; 
    } else { 
    return ""; 
    } 
} 

注1:xmlFreeあなたはxmlFreeを呼び出す前に、NULLをチェックする別の方法にそれをパックする必要があり答えにNULLを取らない場合xmlFreeはstd::unique_ptr

でデリータです。

(これは非常に非効率的です.xmlNodeGetContentは内部データのコピーを作成し、std::stringとして返します。テキストの別のコピーが必要です。少なくとも、呼び出し側のlvalueの文字列の最終コピーは省略さ。)xmlFreeDoc

同じトリック、最初に少し書き換え

if (rc != 0) { 
    // any other xml clean up needed??? 
    return "Empty file found"; 
} 

が、その後

std::unique_ptr<xmlDoc> m_doc(xmlParseFile(m_fileName.c_str()), Cleanup); 
// note the ptr is gone to the unique_ptr 
としてそれを宣言する

および追加の方法

void Cleanup(xmlDocPtr m_doc) { 
    xmlFreeDoc(m_doc); 
    xmlCleanupCharEncodingHandlers(); 
    xmlCleanupParser(); 
} 

m_docスコープCleanupを離れるときに呼び出されます。

不要な作業をしないように、クリーンアップを行う必要があります。

他のすべてのxml関数をいくつかのC++にパックするか、xmlライブラリを変更する必要があります。

関連する問題