我在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;
}
答案 0 :(得分:1)
解决方案是:
mxmlDelete(xmlDocument); // release mem
释放XML树占用的内存。它在文档中进一步提到,我没有阅读该部分。
答案 1 :(得分:-1)
成功加载文件后(代码未检查)
然后在处理文件之后,仍然有指针(mxml_node_t *xmlDocument
),它是指向已分配内存的指针。
指针应该通过以下方式传递给free:free(xmlDocument)
;