2015-05-04 3 views
0

Я разбор некоторых простых XML с помощью C и мини-XML (http://www.msweet.org/projects.php?Z3) в системе Linux:Почему valgrind сообщает об утечке в этом мини-xml-коде?

<?xml version="1.0" encoding="utf-8" ?> 
<quran type="metadata" version="1.0" copyright="(C) 2008-2009 Tanzil.info" license="cc-by"> 
    <suras alias="chapters"> 
     <sura index="1" ayas="7" start="0" name="الفاتحة" tname="Al-Faatiha" ename="The Opening" type="Meccan" order="5" rukus="1" /> 
     <sura index="2" ayas="286" start="7" name="البقرة" tname="Al-Baqara" ename="The Cow" type="Medinan" order="87" rukus="40" /> 
... 

Я получаю сообщение утечки Valgrind в этом коде:

FILE* xmlMetaFile = fopen("/home/muhammad/Development/HifzHelper/dbgen/quran-metadata.xml", "r"); 
mxml_node_t *xmlDocument = mxmlLoadFile(NULL, xmlMetaFile, MXML_IGNORE_CALLBACK); 
for (mxml_node_t* xmlNode = mxmlFindElement(xmlDocument, xmlDocument, "sura", NULL, NULL, MXML_DESCEND); xmlNode != NULL; xmlNode = mxmlFindElement(xmlNode, xmlDocument, "sura", NULL, NULL, MXML_DESCEND)) 
{ 
    ... 
} 

На этой линии особенно :

mxml_node_t *xmlDocument = mxmlLoadFile(NULL, xmlMetaFile, MXML_IGNORE_CALLBACK); 

это странно, так как документация (http://www.msweet.org/documentation/project3/Mini-XML.html#3_4) предписывает, чтобы написать это, как это.

Valgrind выход:

==4045== Memcheck, a memory error detector 
==4045== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==4045== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==4045== Command: ./dbgen 
==4045== 
==4045== 
==4045== HEAP SUMMARY: 
==4045==  in use at exit: 281,994 bytes in 15,534 blocks 
==4045== total heap usage: 244,265 allocs, 228,731 frees, 60,275,346 bytes allocated 
==4045== 
==4045== 281,994 (88 direct, 281,906 indirect) bytes in 1 blocks are definitely lost in loss record 9 of 9 
==4045== at 0x4C2C934: calloc (vg_replace_malloc.c:623) 
==4045== by 0x50F6300: mxml_new (mxml-node.c:751) 
==4045== by 0x50F63A7: mxmlNewElement (mxml-node.c:400) 
==4045== by 0x50F4742: mxml_load_data (mxml-file.c:1953) 
==4045== by 0x400E52: main (dbgen.c:57) 
==4045== 
==4045== LEAK SUMMARY: 
==4045== definitely lost: 88 bytes in 1 blocks 
==4045== indirectly lost: 281,906 bytes in 15,533 blocks 
==4045==  possibly lost: 0 bytes in 0 blocks 
==4045== still reachable: 0 bytes in 0 blocks 
==4045==   suppressed: 0 bytes in 0 blocks 
==4045== 
==4045== For counts of detected and suppressed errors, rerun with: -v 
==4045== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 1 from 1) 

Done. 

Является ли это ошибка в моей программе или мини-XML?

EDIT (полный код):

#include <stdio.h> 
#include <sqlite3.h> 
#include <string.h> 
#include <stdlib.h> 
#include <mxml.h> 

int main(int argc, char *argv[]) 
{ 
    // open connection 
    sqlite3 *conn; 
    sqlite3_initialize(); 
    sqlite3_open_v2("hifzhelper.sl3", &conn, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); 

    // create ayaat table 
    sqlite3_exec(conn, "CREATE TABLE Ayaat (Id INTEGER PRIMARY KEY, SurahNo INTEGER, AyahNo INTEGER, AyahText TEXT, Status INTEGER DEFAULT 0)", NULL, NULL, NULL); 
    sqlite3_exec(conn, "BEGIN TRANSACTION;", NULL, NULL, NULL); 

    // open ayaat data file 
    FILE* ayaatFile = fopen("/home/muhammad/Development/HifzHelper/dbgen/quran.txt", "r"); 
    if(ayaatFile == NULL) 
    { 
     puts("quran file not found"); 
     return 1; 
    } 

    char sql[2048]; 
    char line[2048]; 

    while(fgets(line, 2048, ayaatFile)) 
    { 
     char* parts[3]; 
     parts[0] = strtok(line, "|"); 
     for(int i = 1; i < 3; i++) 
     { 
      parts[i] = strtok (NULL, "|"); 
     } 

     int ayahNo = atoi(parts[0]); 
     int surahNo = atoi(parts[1]); 
     char *ayahText = parts[2]; 
     int status = 0; 

     sprintf(sql, "INSERT INTO Ayaat (SurahNo, AyahNo, AyahText, Status) VALUES (%d, %d, '%s', %d)", surahNo, ayahNo, ayahText, status); 
     sqlite3_exec(conn, sql, NULL, NULL, NULL); 
    } 

    // ayaat index 
    sqlite3_exec(conn, "CREATE INDEX IDX_SurahAyah ON Ayaat (SurahNo, AyahNo);", NULL, NULL, NULL); 
    sqlite3_exec(conn, "END TRANSACTION;", NULL, NULL, NULL); 

    // create surahs table 
    sqlite3_exec(conn, "CREATE TABLE Surahs (Id INTEGER PRIMARY KEY, Name TEXT, AyahCount INTEGER)", NULL, NULL, NULL); 

    // extract surahs 
    sqlite3_exec(conn, "BEGIN TRANSACTION;", NULL, NULL, NULL); 
    FILE* xmlMetaFile = fopen("/home/muhammad/Development/HifzHelper/dbgen/quran-metadata.xml", "r"); 
    mxml_node_t *xmlDocument = mxmlLoadFile(NULL, xmlMetaFile, MXML_IGNORE_CALLBACK); 
    for (mxml_node_t* xmlNode = mxmlFindElement(xmlDocument, xmlDocument, "sura", NULL, NULL, MXML_DESCEND); xmlNode != NULL; xmlNode = mxmlFindElement(xmlNode, xmlDocument, "sura", NULL, NULL, MXML_DESCEND)) 
    { 
     int surahNo = atoi(mxmlElementGetAttr(xmlNode, "index")); 
     const char* surahName = mxmlElementGetAttr(xmlNode, "name"); 
     int ayahCount = atoi(mxmlElementGetAttr(xmlNode, "ayas")); 

     sprintf(sql, "INSERT INTO Surahs (Id, Name, AyahCount) VALUES (%d, '%s', %d)", surahNo, surahName, ayahCount); 
     sqlite3_exec(conn, sql, NULL, NULL, NULL); 
    } 
    sqlite3_exec(conn, "END TRANSACTION;", NULL, NULL, NULL); 

    // create reminder tables 
    sqlite3_exec(conn, "CREATE TABLE Reminders (Id INTEGER PRIMARY KEY AUTOINCREMENT, StartAyah INTEGER, EndAyah INTEGER, TimeFactor INTEGER DEFAULT 0, Due DATETIME, Status INTEGER DEFAULT 0)", NULL, NULL, NULL); 

    // vaccuum 
    sqlite3_exec(conn, "VACUUM;", NULL, NULL, NULL); 

    // cleanup 
    fclose(ayaatFile); 
    fclose(xmlMetaFile); 

    if (NULL != conn) 
     sqlite3_close(conn); 

    sqlite3_shutdown(); 
    return 0; 
} 
+0

Valgrind сообщает вам, где проблема, исправить код, и если вам нужна помощь, отправьте его и إن شاء الله, я могу вам помочь. –

+0

@iharob Я опубликовал полный код, строка, о которой идет речь, верна, насколько мне известно, в соответствии с документацией mini-xml, поэтому я не могу понять эту утечку. – sprocket12

+1

Есть ли функция 'mxml_delete' или аналогичная функция? –

ответ

-1

После успешной загрузки файла (который код не проверить на) затем после обработки файла, есть еще указатель (mxml_node_t *xmlDocument), который является указателем к выделенной памяти.

Указатель должен быть передан через: free(xmlDocument);

+0

Можете ли вы поддержать это со ссылкой на документацию 'mini-xml'? –

1

Решение было сделать:

mxmlDelete(xmlDocument); // release mem 

, чтобы освободить память держится на дереве XML. Это было указано ниже в документации, и я не читал эту часть.