我在使用libxml2时遇到了问题。
我正在尝试复制节点列表并将其保存到文件中。代码构建并运行但是当我在valgrind中运行它时会出现错误。
这是我的测试代码:test_libxml.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#define RSS_XML "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"\
"<rss version=\"2.0\">\n"\
"\t<channel>\n"\
"\t\t<item>\n"\
"\t\t\t<title>Some Title</title>\n"\
"\t\t\t<description>Some Description</description>\n"\
"\t\t</item>\n\t\t<item>\n"\
"\t\t\t<title>Another Title</title>\n"\
"\t\t\t<description>Another Description</description>\n"\
"\t\t</item>\n"\
"\t</channel>\n"\
"</rss>\n"
static const char document [] = RSS_XML;
static int parse_rss (const char *content, int content_len);
static void parse_channel (xmlNodePtr channel);
static void save_item (xmlNodePtr item);
int main (int argc, char *argv[])
{
int ret = 1;
xmlInitParser ();
ret = parse_rss (document, sizeof (document) - 1);
xmlCleanupParser();
xmlMemoryDump();
return ret;
}
static int parse_rss (const char *content, int content_len)
{
xmlParserCtxtPtr parser;
xmlDocPtr doc;
parser = xmlNewParserCtxt ();
if (parser == NULL) {
fprintf (stderr, "Failed to creste parser\n");
return 1;
}
doc = xmlCtxtReadMemory (parser, content, content_len, NULL, NULL, 0);
if (doc == NULL) {
xmlFreeParserCtxt (parser);
fprintf (stderr, "Failed to parse document\n");
return 1;
}
xmlNodePtr root = xmlDocGetRootElement (doc);
xmlNodePtr node = root->children;
while (node) {
if (node->type == XML_ELEMENT_NODE
&& xmlStrEqual (node->name, BAD_CAST "channel"))
{
parse_channel (node);
}
node = node->next;
}
xmlFreeDoc (doc);
xmlFreeParserCtxt (parser);
return 0;
}
static void parse_channel (xmlNodePtr channel)
{
xmlNodePtr node = channel->children;
while (node) {
if (node->type == XML_ELEMENT_NODE
&& xmlStrEqual (node->name, BAD_CAST "item"))
{
save_item (node);
}
node = node->next;
}
}
static void save_item (xmlNodePtr item)
{
static int i = 0;
char filename [200];
sprintf (filename, "item_%d.xml", i++);
xmlDocPtr doc = xmlNewDoc (NULL);
if (doc == NULL) {
return;
}
xmlNodePtr temp = xmlCopyNodeList (item);
if (temp == NULL) {
xmlFreeDoc (doc);
return;
}
xmlDocSetRootElement (doc, temp);
xmlSaveFile (filename, doc);
xmlUnlinkNode (temp);
xmlFreeNodeList (temp);
xmlFreeDoc (doc);
}
这是valgrind输出:
==6581== Memcheck, a memory error detector
==6581== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6581== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==6581== Command: ./build/test_libxml
==6581==
==6581==
==6581== HEAP SUMMARY:
==6581== in use at exit: 741 bytes in 22 blocks
==6581== total heap usage: 145 allocs, 123 frees, 26,427 bytes allocated
==6581==
==6581== 741 (120 direct, 621 indirect) bytes in 2 blocks are definitely lost in loss record 9 of 9
==6581== at 0x4006ADD: malloc (vg_replace_malloc.c:291)
==6581== by 0x8076696: xmlStaticCopyNode (in test_libxml)
==6581== by 0x8076B70: xmlStaticCopyNodeList (in test_libxml)
==6581== by 0x8076C71: xmlCopyNodeList (in test_libxml)
==6581== by 0x8049925: save_item (test_libxml.c:107)
==6581== by 0x80498C2: parse_channel (test_libxml.c:88)
==6581== by 0x804984F: parse_rss (test_libxml.c:68)
==6581== by 0x8049734: main (test_libxml.c:33)
==6581==
==6581== LEAK SUMMARY:
==6581== definitely lost: 120 bytes in 2 blocks
==6581== indirectly lost: 621 bytes in 20 blocks
==6581== possibly lost: 0 bytes in 0 blocks
==6581== still reachable: 0 bytes in 0 blocks
==6581== suppressed: 0 bytes in 0 blocks
==6581==
==6581== For counts of detected and suppressed errors, rerun with: -v
==6581== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 14 from 8)
libxml2版本是2.9.1
感谢任何帮助。谢谢
答案 0 :(得分:0)
正如@nwellnhof所说
正确使用的函数确实是xmlCopyNode。
这是正确的代码
static void save_item (xmlNodePtr item)
{
static int i = 0;
char filename [200];
sprintf (filename, "item_%d.xml", i++);
xmlDocPtr doc = xmlNewDoc (NULL);
if (doc == NULL) {
return;
}
xmlNodePtr temp = xmlCopyNode(item, 1);
if (temp == NULL) {
xmlFreeDoc (doc);
return;
}
xmlDocSetRootElement (doc, temp);
xmlSaveFile (filename, doc);
xmlFreeDoc (doc);
}