我正在构建一个程序,使用 libxml2 v2.13 在两个 xml 文件之间进行合并验证。
总而言之,在尝试验证 DOM 之间的一些合并(使用 libxml2 的模式和模式功能)时,我注意到当取消链接然后删除子节点时,如果然后我尝试添加新的子节点,我会收到内存泄漏和错误的报告瓦尔格林德。
我已经用这个示例程序重现了这个问题:
/**
* section: Parsing
* synopsis: Parse an XML document in memory to a tree and free it
* purpose: Demonstrate the use of xmlReadMemory() to read an XML file
* into a tree and xmlFreeDoc() to free the resulting tree
* usage: parse3
* test: parse3
* author: Daniel Veillard
* copy: see Copyright for the status of this software.
*/
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <string.h>
static const char *document = "<doc/>";
static xmlNodePtr findNode( xmlNodePtr sibling ,char * node_name){
xmlNodePtr next_sibling = sibling;
while(next_sibling){
if(strncmp((char*)next_sibling->name, node_name, strlen(node_name))){
break;
}
}
return next_sibling;
}
/**
* example3Func:
* @content: the content of the document
* @length: the length in bytes
*
* Parse the in memory document and free the resulting tree
*/
static void
example3Func(const char *content, int length) {
xmlDocPtr doc; /* the resulting document tree */
/*
* The document being in memory, it have no base per RFC 2396,
* and the "noname.xml" argument will serve as its base.
*/
doc = xmlReadMemory(content, length, "customization.xml", NULL, 0);
if (doc == NULL) {
fprintf(stderr, "Failed to parse document\n");
return;
}else{
fprintf(stdout, "DOM loaded\n");
}
xmlNodePtr rec_node = findNode(doc->children,"recording_configurations");
if(rec_node){
fprintf(stdout, "Found rec_node\n");
xmlNodePtr config_node = findNode(rec_node,"configuration_1");
xmlUnlinkNode(config_node);
xmlReconciliateNs(doc, rec_node);
xmlFreeNode(config_node);
config_node = xmlNewChild(rec_node, NULL, (xmlChar*)"configuration_2",NULL);
printf("%s\n",rec_node->children->name);
}
xmlFreeDoc(doc);
}
int main(void) {
/*
* this initialize the library and check potential ABI mismatches
* between the version it was compiled for and the actual shared
* library used.
*/
example3Func(document, 6);
/*
* Cleanup function for the XML library.
*/
xmlCleanupParser();
/*
* this is to debug memory for regression tests
*/
xmlMemoryDump();
return(0);
}
而 valgrind 的输出将是:
jlm@esswlab3:~/projects/xmlTests/parser$ make
cc -MM -Wall -O2 -I/usr/include/libxml2 parser.c > parser.dep
cc -Wall -O2 -I/usr/include/libxml2 -o parser.o -c parser.c
cc -o parser parser.o -lm -lz -lsystemd -lxml2
jlm@esswlab3:~/projects/xmlTests/parser$ valgrind ./parser
==310107== Memcheck, a memory error detector
==310107== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==310107== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==310107== Command: ./parser
==310107==
DOM loaded
Found rec_node
==310107== Invalid read of size 4
==310107== at 0x48DC617: xmlNewChild (tree.c:2913)
==310107== by 0x109282: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d332f8 is 8 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
==310107== Invalid read of size 8
==310107== at 0x48DC680: xmlNewChild (tree.c:2915)
==310107== by 0x109282: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d33330 is 64 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
==310107== Invalid read of size 8
==310107== at 0x48DC689: xmlNewChild (tree.c:2915)
==310107== by 0x109282: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d33338 is 72 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
==310107== Invalid read of size 8
==310107== at 0x48DC639: xmlNewChild (tree.c:2936)
==310107== by 0x109282: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d33330 is 64 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
==310107== Invalid read of size 8
==310107== at 0x48DC63D: xmlNewChild (tree.c:2937)
==310107== by 0x109282: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d33308 is 24 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
==310107== Invalid write of size 8
==310107== at 0x48DC698: xmlNewChild (tree.c:2938)
==310107== by 0x109282: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d33308 is 24 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
==310107== Invalid write of size 8
==310107== at 0x48DC69C: xmlNewChild (tree.c:2939)
==310107== by 0x109282: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d33310 is 32 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
==310107== Invalid read of size 8
==310107== at 0x109283: main (in /home/jlm/projects/xmlTests/parser)
==310107== Address 0x4d33308 is 24 bytes inside a block of size 120 free'd
==310107== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x10926F: main (in /home/jlm/projects/xmlTests/parser)
==310107== Block was alloc'd at
==310107== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==310107== by 0x48D78C4: xmlNewNodeEatName (tree.c:2247)
==310107== by 0x48DC6D2: xmlNewDocNodeEatName (tree.c:2319)
==310107== by 0x48D326B: xmlSAX2StartElementNs (SAX2.c:2101)
==310107== by 0x48BFCA2: xmlParseStartTag2 (parser.c:9497)
==310107== by 0x48C265F: xmlParseElementStart (parser.c:9893)
==310107== by 0x48C43DC: xmlParseElement (parser.c:9828)
==310107== by 0x48C99E7: xmlParseDocument (parser.c:10618)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13728)
==310107== by 0x48CD251: xmlCtxtParseDocument (parser.c:13712)
==310107== by 0x48CD670: xmlReadMemory (parser.c:13855)
==310107== by 0x1091E4: main (in /home/jlm/projects/xmlTests/parser)
==310107==
configuration_2
==310107==
==310107== HEAP SUMMARY:
==310107== in use at exit: 120 bytes in 1 blocks
==310107== total heap usage: 27 allocs, 26 frees, 12,862 bytes allocated
==310107==
==310107== LEAK SUMMARY:
==310107== definitely lost: 120 bytes in 1 blocks
==310107== indirectly lost: 0 bytes in 0 blocks
==310107== possibly lost: 0 bytes in 0 blocks
==310107== still reachable: 0 bytes in 0 blocks
==310107== suppressed: 0 bytes in 0 blocks
==310107== Rerun with --leak-check=full to see details of leaked memory
==310107==
==310107== For lists of detected and suppressed errors, rerun with: -s
==310107== ERROR SUMMARY: 8 errors from 8 contexts (suppressed: 0 from 0)
注意,我已经编译了 libxml2 源代码,以便从 valgrind 获取 libxml2 中的详细跟踪信息。
我是否缺少与 DOM 或命名空间的任何类型的取消链接?我的工作流程正确吗?有人知道这里的问题是什么吗?
提前致谢。
我认为
findNode
函数中的错误是由 if
语句中的错误条件引起的。 strncmp
函数用于将节点名称与提供的 node_name
字符串进行比较。然而,if
语句中的条件是检查字符串是否不相等,而不是检查它们是否相等。
所以这一行:
if(strncmp((char*)next_sibling->name, node_name, strlen(node_name))){
必须更改为:
if (!strncmp((char*)next_sibling->name, node_name, strlen(node_name)))