c - 为什么 valgrind 报告此 mini-xml 代码中存在泄漏?

标签 c xml parsing memory-leaks valgrind

我正在 Linux 系统上使用 c 和 mini-xml (http://www.msweet.org/projects.php?Z3) 解析一些简单的 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.

这是我的程序或 mini-xml 中的错误吗?

编辑(完整代码):

#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;
}

最佳答案

解决方案是:

mxmlDelete(xmlDocument); // release mem

释放 XML 树占用的内存。文档中进一步提到了这一点,但我没有阅读该部分。

关于c - 为什么 valgrind 报告此 mini-xml 代码中存在泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30040279/

相关文章:

android - 以不同分辨率缩放图像 XML

c - 寻找最大和第二大数

c - 二进制 "become"什么时候是十进制或十六进制?十六进制 "faster"是十进制吗?

c - Onvif - 试图了解它是如何工作的

c# - 有没有办法通过单个字符串编写 xml 注释 <summary>

具有多线程的 Java 解析器

c# - 如何从外部文件显示 C# 源代码?

java - 在antlr语法g4文件中使用Java代码

C - 成员引用基类型 'int' 不是结构或 union

无法使用 frama-c 分析 openmp 代码