我编写了一个xml编辑器,可以在没有警告或错误的情况下编译好,并且运行时不会出现内存泄漏。但是当我运行valgrind并且无法弄清楚导致它的原因时,我一直收到此错误Invalid Free()
。
我认为它可能与在null或释放指针上运行free
命令有关但我无法指出它?是什么导致了它,我如何从报告中得知?
(这是我的完整代码,抱歉有点长)
#ifndef _XML_header
#define MAX 10
xmlDoc *doc;
xmlNode *root;
int count;
char *cursor;
struct child
{
const xmlChar *grandfather;
const xmlChar *father;
const xmlChar *name;
xmlNode *node;
};
struct spouse
{
const xmlChar *husband;
const xmlChar *name;
struct child **children;
xmlNode *node;
};
struct special
{
const xmlChar *name;
const xmlChar *value;
const xmlChar *details;
xmlNode *node;
};
struct selectedNode
{
const xmlChar *name;
const xmlChar *father;
const xmlChar *grandfather;
struct spouse **spouses;
struct special **specialItems;
struct spouse *selectedSpouse;
struct special *selectedSpecialItem;
xmlNode *node;
};
struct child **cont;
struct selectedNode *selected;
void check(int condition);
#endif
#include <libxml2/libxml/parser.h>
#include <libxml2/libxml/tree.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "xml.h"
xmlNode *getParent(xmlNode *node)
{
xmlNode *cur = node->parent;
while (cur != NULL)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, (const xmlChar *) "child"))
return cur;
cur = cur->parent;
}
return NULL;
}
const xmlChar *getContent(xmlNode *node, const xmlChar *type)
{
xmlNode *cur;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, type))
return xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
}
return (const xmlChar *) "none";
}
const xmlChar *getName(xmlNode *node)
{
return getContent(node, (const xmlChar *) "name");
}
const xmlChar *getGender(xmlNode *node)
{
return getContent(node, (const xmlChar *) "gender");
}
const xmlChar *getBirthdate(xmlNode *node)
{
return getContent(node, (const xmlChar *) "born");
}
const xmlChar *getDeathdate(xmlNode *node)
{
return getContent(node, (const xmlChar *) "died");
}
int setContent(xmlNode *node, const xmlChar *nodeName, const xmlChar *content)
{
xmlNode *cur;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, nodeName))
{
xmlNodeSetContent(cur, content);
return 0;
}
}
return 1;
}
int setName(xmlNode *node, const xmlChar *name)
{
return setContent(node, (const xmlChar *) "name", name);
}
int setGender(xmlNode *node, const xmlChar *gender)
{
return setContent(node, (const xmlChar *) "gender", gender);
}
int setBirthdate(xmlNode *node, const xmlChar *born)
{
return setContent(node, (const xmlChar *) "born", born);
}
int setDeathdate(xmlNode *node, const xmlChar *died)
{
return setContent(node, (const xmlChar *) "died", died);
}
struct child *getChild(xmlNode *node, const xmlChar *father, const xmlChar *grandfather)
{
check(!xmlStrcmp(node->name, (const xmlChar *) "child"));
struct child *temp = calloc(1, sizeof(struct child));
temp->father = father;
temp->grandfather = grandfather;
temp->name = getName(node);
temp->node = node;
return temp;
}
struct child **getChildren(xmlNode *node, const xmlChar *father, const xmlChar *grandfather)
{
check(!xmlStrcmp(node->name, (const xmlChar *) "spouse"));
xmlNode *cur;
int i = 0;
struct child **childrenCont = NULL;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, (const xmlChar *) "children"))
{
if (!cur->children) return NULL;
childrenCont = calloc(1, sizeof(struct child *));
childrenCont[0] = NULL;
for (cur = cur->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE)
{
childrenCont = realloc(childrenCont, (i + 2) * sizeof(struct child *));
childrenCont[i] = getChild(cur, father, grandfather);
childrenCont[i + 1] = NULL;
i++;
}
}
break;
}
}
return childrenCont;
}
struct spouse *getSpouse(xmlNode *node, const xmlChar *husband, const xmlChar *fatherinlaw)
{
check(!xmlStrcmp(node->name, (const xmlChar *) "spouse"));
struct spouse *temp = calloc(1, sizeof(struct spouse));
temp->name = getName(node);
temp->children = getChildren(node, husband, fatherinlaw);
temp->husband = husband;
temp->node = node;
return temp;
}
struct spouse **getSpouses(xmlNode *node, const xmlChar *husband, const xmlChar *fatherinlaw)
{
check(!xmlStrcmp(node->name, (const xmlChar *) "child"));
xmlNode *cur;
int i = 0;
struct spouse **spousesCont = NULL;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, (const xmlChar *) "spouses"))
{
if (!cur->children) return NULL;
spousesCont = calloc(1, sizeof(struct spouse *));
spousesCont[0] = NULL;
for (cur = cur->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE)
{
spousesCont = realloc(spousesCont, (i + 2) * sizeof(struct spouse *));
spousesCont[i] = getSpouse(cur, husband, fatherinlaw);
spousesCont[i + 1] = NULL;
i++;
}
}
break;
}
}
return spousesCont;
}
struct special *getSpecialItem(xmlNode *node)
{
check(!xmlStrcmp(node->name, (const xmlChar *) "item"));
struct special *temp = calloc(1, sizeof(struct special));
xmlNode *cur;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE)
{
if (!xmlStrcmp(cur->name, (const xmlChar *) "name"))
temp->name = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
else if (!xmlStrcmp(cur->name, (const xmlChar *) "value"))
temp->value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
else if (!xmlStrcmp(cur->name, (const xmlChar *) "details"))
temp->details = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
}
}
temp->node = node;
return temp;
}
struct special **getSpecial(xmlNode *node)
{
check(!xmlStrcmp(node->name, (const xmlChar *) "child"));
xmlNode *cur;
int i = 0;
struct special **specialCont = calloc(1, sizeof(struct special *));
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, (const xmlChar *) "special"))
{
for (cur = cur->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE)
{
specialCont = realloc(specialCont, (i + 2) * sizeof(struct special *));
specialCont[i] = getSpecialItem(cur);
specialCont[i + 1] = NULL;
i++;
}
}
break;
}
}
return specialCont;
}
void addChild(xmlNode *node, const xmlChar *name, const xmlChar *born, const xmlChar *died)
{
check(xmlStrcmp(node->name, (const xmlChar *) "spouse"));
xmlNode *cur;
xmlNode *childrenCont = NULL;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, (const xmlChar *) "children"))
childrenCont = cur;
}
if (childrenCont == NULL) childrenCont = xmlNewChild(node, NULL, (const xmlChar *) "children", NULL);
xmlNewChild(childrenCont, NULL, (const xmlChar *) "name", name);
xmlNewChild(childrenCont, NULL, (const xmlChar *) "born", born);
xmlNewChild(childrenCont, NULL, (const xmlChar *) "died", died);
xmlNewChild(childrenCont, NULL, (const xmlChar *) "spouses", NULL);
xmlNewChild(childrenCont, NULL, (const xmlChar *) "special", NULL);
}
void addSpouse(xmlNode *node, const xmlChar *name, const xmlChar *born, const xmlChar *died)
{
check(xmlStrcmp(node->name, (const xmlChar *) "child"));
xmlNode *cur;
xmlNode *spousesCont = NULL;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, (const xmlChar *) "spouses"))
spousesCont = cur;
}
if (spousesCont == NULL) spousesCont = xmlNewChild(node, NULL, (const xmlChar *) "spouses", NULL);
xmlNewChild(spousesCont, NULL, (const xmlChar *) "name", name);
xmlNewChild(spousesCont, NULL, (const xmlChar *) "born", born);
xmlNewChild(spousesCont, NULL, (const xmlChar *) "died", died);
xmlNewChild(spousesCont, NULL, (const xmlChar *) "children", NULL);
xmlNewChild(spousesCont, NULL, (const xmlChar *) "special", NULL);
}
void addSpecial(xmlNode *node, const xmlChar *name, const xmlChar *value, const xmlChar *details)
{
check(!xmlStrcmp(node->name, (const xmlChar *) "child"));
xmlNode *cur;
xmlNode *specialCont = NULL;
for (cur = node->children; cur != NULL; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && !xmlStrcmp(cur->name, (const xmlChar *) "special"))
specialCont = cur;
}
if (specialCont == NULL) specialCont = xmlNewChild(node, NULL, (const xmlChar *) "special", NULL);
xmlNewChild(specialCont, NULL, (const xmlChar *) "name", name);
xmlNewChild(specialCont, NULL, (const xmlChar *) "value", value);
xmlNewChild(specialCont, NULL, (const xmlChar *) "details", details);
}
void deleteNode(xmlNode *node)
{
xmlUnlinkNode(node);
xmlFreeNode(node);
}
void printResults()
{
int i = 0;
while (cont[i] != NULL)
{
printf("%d- %s son of %s son of %s\n", i + 1,
cont[i]->name, cont[i]->father, cont[i]->grandfather);
i++;
}
}
void freeChild(struct child *node)
{
if (node == NULL) return;
xmlFree((xmlChar *) node->father);
xmlFree((xmlChar *) node->grandfather);
xmlFree((xmlChar *) node->name);
free(node);
}
void freeChildrenCont(struct child **childrenCont)
{
int i = 0;
if (childrenCont == NULL) return;
while (childrenCont[i] != NULL)
{
freeChild(childrenCont[i]);
i++;
}
free(childrenCont);
}
void freeSpouse(struct spouse *node)
{
if (node == NULL) return;
if (node->children) freeChildrenCont(node->children);
xmlFree((xmlChar *) node->husband);
xmlFree((xmlChar *) node->name);
free(node);
}
void freeSpousesCont(struct spouse **spousesCont)
{
int i = 0;
if (spousesCont == NULL) return;
while (spousesCont[i] != NULL)
{
freeSpouse(spousesCont[i]);
i++;
}
free(spousesCont);
}
void freeSpecial(struct special *item)
{
if (item == NULL) return;
xmlFree((xmlChar *) item->name);
xmlFree((xmlChar *) item->value);
xmlFree((xmlChar *) item->details);
free(item);
}
void freeSpecialCont(struct special **specialCont)
{
int i = 0;
if (specialCont == NULL) return;
while (specialCont[i] != NULL)
{
freeSpecial(specialCont[i]);
i++;
}
free(specialCont);
}
void freeCont()
{
freeChildrenCont(cont);
}
void resetCont()
{
if (cont != NULL)
{
int i = 0;
while (cont[i] != NULL)
{
freeChild(cont[i]);
i++;
}
memset(cont, 0, MAX * sizeof(struct cont *));
}
count = 0;
}
void freeSelected()
{
if (selected == NULL) return;
if (selected->father) xmlFree((xmlChar *) selected->father);
if (selected->grandfather) xmlFree((xmlChar *) selected->grandfather);
if (selected->name) xmlFree((xmlChar *) selected->name);
if (selected->spouses) freeSpousesCont(selected->spouses);
if (selected->specialItems) freeSpecialCont(selected->specialItems);
if (selected->selectedSpouse) freeSpouse(selected->selectedSpouse);
if (selected->selectedSpecialItem) freeSpecial(selected->selectedSpecialItem);
free(selected);
selected = NULL;
}
int getOption()
{
char input[20];
int n = 0;
if (fgets(input, sizeof(input), stdin)) sscanf(input, "%d", &n);
return n;
}
void capitalize(char word[])
{
if (isalpha(word[0])) word[0] = toupper(word[0]);
}
void printSpouses()
{
int i = 0;
if (selected)
{
printf("Wives:\n");
if (selected->spouses == NULL) printf("\tnone\n");
else
{
if (selected->spouses[i] == NULL) printf("\tnone\n");
while (selected->spouses[i] != NULL)
{
printf("\t %d. %s\n", i + 1, selected->spouses[i]->name);
i++;
}
}
}
}
void printChildren(struct spouse *node)
{
int i = 0;
if (selected)
{
printf("Children:\n");
if (node->children == NULL) printf("\tnone\n");
else
{
if (node->children[i] == NULL) printf("\tnone\n");
while (node->children[i] != NULL)
{
printf("\t%d. %s\n", i + 1, node->children[i]->name);
i++;
}
}
}
}
void printSpecialItem(struct special *item, int n)
{
if (n) printf("Item:\n");
else printf("Item %d:\n", n);
printf("\tName: %s\n", item->name);
printf("\tValue: %s\n", item->value);
printf("\tDetails: %s\n", item->details);
}
void printSpecial()
{
int i = 0;
if (selected == NULL) printf("Must select node first\n");
else if (selected->specialItems == NULL || selected->specialItems[0] == NULL)
printf("Special:\n\tNo special items found\n");
else
{
printf("special:\n");
while (selected->specialItems[i] != NULL)
{
printSpecialItem(selected->specialItems[i], i + 1);
i++;
}
}
}
void die()
{
freeSelected();
freeCont();
free(cursor);
xmlFreeDoc(doc);
xmlCleanupParser();
}
void check(int condition)
{
if (!condition)
{
printf("check failed\n");
die();
exit(1);
}
}
void showInfo()
{
int i = 0;
const xmlChar *born, *died, *gender;
if (selected)
{
printf("Name: %s\n", selected->name);
printf("Father: %s\n", selected->father);
printf("Grandfather: %s\n", selected->grandfather);
printf("Born: %s\n", (born = getBirthdate(selected->node)));
printf("Died: %s\n", (died = getDeathdate(selected->node)));
printf("Gender: %s\n", (gender = getGender(selected->node)));
printSpouses();
if (selected->spouses != NULL && selected->spouses[0] != NULL)
{
for (i = 0; selected->spouses[i] != NULL; i++)
{
printChildren(selected->spouses[i]);
}
}
else printf("Children:\n\tnone\n");
xmlFree((xmlChar *) born);
xmlFree((xmlChar *) died);
xmlFree((xmlChar *) gender);
}
else printf("Must select node first\n");
}
int find(xmlNode *node, const xmlChar *key, const xmlChar *grandfather, const xmlChar *father)
{
const xmlChar *name;
xmlNode *cur;
for (cur = node; cur != NULL && count < MAX; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE)
{
if (!xmlStrcmp(cur->name, (const xmlChar *) "child"))
{
name = getName(cur);
if (!xmlStrcmp(name, key))
{
cont[count] = malloc(sizeof(struct child));
cont[count]->grandfather = xmlStrdup(grandfather);
cont[count]->father = xmlStrdup(father);
cont[count]->name = xmlStrdup(name);
cont[count]->node = cur;
count++;
}
if (cur->children) find(cur->children, key, name, father);
xmlFree((xmlChar *) name);
}
else if (cur->children)
find(cur->children, key, father, grandfather);
}
}
return (count > 0) ? 1 : 0;
}
void selectNode(struct child *node, const char *type, int option)
{
xmlNode *cur;
if (selected == NULL && strcmp(type, "node"))
{
printf("Must select a node first\n");
}
else if (!strcmp(type, "node"))
{
freeSelected();
selected = calloc(1, sizeof(struct selectedNode));
selected->name = xmlStrdup(node->name);
selected->father = xmlStrdup(node->father);
selected->grandfather = xmlStrdup(node->grandfather);
selected->node = node->node;
selected->spouses = getSpouses(selected->node, selected->father, selected->grandfather);
selected->specialItems = getSpecial(selected->node);
selected->selectedSpouse = NULL;
selected->selectedSpecialItem = NULL;
memset(cursor, 0, strlen(cursor));
strcpy(cursor, (char *) node->name);
cursor = strcat(cursor, " > ");
}
else if (!strcmp(type, "spouse"))
{
selected->selectedSpouse = selected->spouses[option];
memset(cursor, 0, strlen(cursor));
cursor = (char *) selected->name;
cursor = strcat(cursor, ":");
cursor = strcat(cursor, (char *) selected->selectedSpouse->name);
cursor = strcat(cursor, " > ");
}
else if (!strcmp(type, "special"))
{
selected->selectedSpecialItem = selected->specialItems[option];
memset(cursor, 0, strlen(cursor));
strcpy(cursor, (char *) selected->name);
cursor = strcat(cursor, "[");
cursor = strcat(cursor, (char *) selected->selectedSpecialItem->name);
cursor = strcat(cursor, "] > ");
}
else if (!strcmp(type, "child"))
{
if (selected->selectedSpouse != NULL)
selectNode(selected->selectedSpouse->children[option], (const char *) "node", -1);
else printf("Spouse is not selected\n");
}
else if (!strcmp(type, "father"))
{
cur = getParent(selected->node);
check(!xmlStrcmp(getName(cur), selected->father));
if (cur)
{
selected->name = selected->father;
selected->father = selected->grandfather;
selected->node = cur;
selected->spouses = getSpouses(cur, selected->name, selected->father);
selected->specialItems = getSpecial(cur);
selected->selectedSpouse = NULL;
selected->selectedSpecialItem = NULL;
cur = getParent(cur);
if (cur) selected->grandfather = getName(cur);
memset(cursor, 0, strlen(cursor));
strcpy(cursor, (char *) selected->name);
cursor = strcat(cursor, " > ");
}
else printf("Parent node was not found\n");
}
else printf("Unrecognized option %s", (char *) type);
}
void execute(char command[], char value[], char option[])
{
int rv = 0;
int n = 0;
const xmlChar *none = (const xmlChar *) "none";
if (!strcmp(command, "find"))
{
capitalize(value);
if (value[0] == '\0') printf("Invalid search value\n");
else if ((rv = find(root, (const xmlChar *) value, none, none)) == 1)
{
printf("Found:\n");
printResults();
printf("Choose a Person's (number) to select, or (0) to cancel > ");
if ((n = getOption()) > 0 && n - 1 < MAX && cont[n - 1] != NULL)
{
selectNode(cont[n - 1], (const char *) "node", -1);
}
resetCont();
}
else printf("Nothing found for %s.\n", value);
}
else if (!strcmp(command, "info")) showInfo();
else if (!strcmp(command, "list"))
{
if (selected == NULL) printf("Must select a node first\n");
else
{
if (!strcmp(value, "spouses")) printSpouses();
else if (!strcmp(value, "children"))
{
if (selected->selectedSpouse != NULL) printChildren(selected->selectedSpouse);
else printf("Must select a spouse first\n");
}
else if (!strcmp(value, "special")) printSpecial();
else printf("Invalid command\n");
}
}
else printf("Invalid command\n");
}
int main(int argc, char *argv[])
{
LIBXML_TEST_VERSION
if (argc < 2)
{
printf("Usage: xml filename.xml\n");
return 1;
}
char input[40];
char command[40];
char value[40];
char option[40];
cursor = malloc(100 * sizeof(char));
strcpy(cursor, "> ");
count = 0;
cont = calloc(MAX, sizeof(struct child*));
selected = NULL;
if ((doc = xmlReadFile(argv[1], NULL, 0)) == NULL)
{
printf("error: could not parse file %s\n", argv[1]);
exit(-1);
}
root = xmlDocGetRootElement(doc);
while(1)
{
command[0] = '\0';
value[0] = '\0';
option[0] = '\0';
printf("%s", cursor);
if (fgets(input, sizeof(input), stdin)) sscanf(input, "%s %s %s", command, value, option);
if (!strcmp(command, "exit")) break;
execute(command, value, option);
}
die();
return 0;
}
valgrind --leak-check=full --track-origins=yes -v ./xml data.xml
.....(some valgrind initializing output).....
> find luke
--16891-- REDIR: 0x4238b60 (__GI_memchr) redirected to 0x402e7d0 (__GI_memchr)
--16891-- REDIR: 0x42397e0 (__GI_memcpy) redirected to 0x402f090 (__GI_memcpy)
--16891-- REDIR: 0x423b490 (__GI___rawmemchr) redirected to 0x4030ea0 (__GI___rawmemchr)
Found:
1- Luke son of Mike son of John
2- Luke son of John son of none
Choose a Person's (number) to select, or (0) to cancel > 2
--16891-- REDIR: 0x42e8cc0 (__memset_sse2) redirected to 0x4030820 (memset)
Luke > find john
Found:
1- John son of none son of none
Choose a Person's (number) to select, or (0) to cancel > 1
John > find mike
Found:
1- Mike son of John son of none
Choose a Person's (number) to select, or (0) to cancel > 1
==16891== Invalid free() / delete / delete[] / realloc()
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x80490D7: freeChild (xml.c:286)
==16891== by 0x8049132: freeChildrenCont (xml.c:298)
==16891== by 0x804916A: freeSpouse (xml.c:307)
==16891== by 0x80491C2: freeSpousesCont (xml.c:319)
==16891== by 0x804939C: freeSelected (xml.c:372)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891== Address 0x440f770 is 0 bytes inside a block of size 5 free'd
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x804935F: freeSelected (xml.c:369)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891==
==16891== Invalid free() / delete / delete[] / realloc()
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x80490E2: freeChild (xml.c:287)
==16891== by 0x8049132: freeChildrenCont (xml.c:298)
==16891== by 0x804916A: freeSpouse (xml.c:307)
==16891== by 0x80491C2: freeSpousesCont (xml.c:319)
==16891== by 0x804939C: freeSelected (xml.c:372)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891== Address 0x440f7a8 is 0 bytes inside a block of size 5 free'd
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x8049374: freeSelected (xml.c:370)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891==
==16891== Invalid free() / delete / delete[] / realloc()
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x8049175: freeSpouse (xml.c:308)
==16891== by 0x80491C2: freeSpousesCont (xml.c:319)
==16891== by 0x804939C: freeSelected (xml.c:372)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891== Address 0x440f770 is 0 bytes inside a block of size 5 free'd
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x804935F: freeSelected (xml.c:369)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891==
Mike > exit
==16891==
==16891== HEAP SUMMARY:
==16891== in use at exit: 0 bytes in 0 blocks
==16891== total heap usage: 566 allocs, 590 frees, 68,257 bytes allocated
==16891==
==16891== All heap blocks were freed -- no leaks are possible
==16891==
==16891== ERROR SUMMARY: 24 errors from 3 contexts (suppressed: 0 from 0)
==16891==
==16891== 2 errors in context 1 of 3:
==16891== Invalid free() / delete / delete[] / realloc()
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x8049175: freeSpouse (xml.c:308)
==16891== by 0x80491C2: freeSpousesCont (xml.c:319)
==16891== by 0x804939C: freeSelected (xml.c:372)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891== Address 0x440f770 is 0 bytes inside a block of size 5 free'd
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x804935F: freeSelected (xml.c:369)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891==
==16891==
==16891== 11 errors in context 2 of 3:
==16891== Invalid free() / delete / delete[] / realloc()
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x80490E2: freeChild (xml.c:287)
==16891== by 0x8049132: freeChildrenCont (xml.c:298)
==16891== by 0x804916A: freeSpouse (xml.c:307)
==16891== by 0x80491C2: freeSpousesCont (xml.c:319)
==16891== by 0x804939C: freeSelected (xml.c:372)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891== Address 0x440f7a8 is 0 bytes inside a block of size 5 free'd
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x8049374: freeSelected (xml.c:370)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891==
==16891==
==16891== 11 errors in context 3 of 3:
==16891== Invalid free() / delete / delete[] / realloc()
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x80490D7: freeChild (xml.c:286)
==16891== by 0x8049132: freeChildrenCont (xml.c:298)
==16891== by 0x804916A: freeSpouse (xml.c:307)
==16891== by 0x80491C2: freeSpousesCont (xml.c:319)
==16891== by 0x804939C: freeSelected (xml.c:372)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891== Address 0x440f770 is 0 bytes inside a block of size 5 free'd
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x804935F: freeSelected (xml.c:369)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891==
==16891== ERROR SUMMARY: 24 errors from 3 contexts (suppressed: 0 from 0)
答案 0 :(得分:2)
Valgrind告诉你的是这样的例子:
==16891== Invalid free() / delete / delete[] / realloc()
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x8049175: freeSpouse (xml.c:308)
==16891== by 0x80491C2: freeSpousesCont (xml.c:319)
==16891== by 0x804939C: freeSelected (xml.c:372)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891== Address 0x440f770 is 0 bytes inside a block of size 5 free'd
==16891== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==16891== by 0x804935F: freeSelected (xml.c:369)
==16891== by 0x804A3DB: selectNode (xml.c:544)
==16891== by 0x804A98F: execute (xml.c:622)
==16891== by 0x8048BEA: main (xml.c:706)
==16891==
是指您通过free()
在同一指针上调用freeSpouse (xml.c:308)
之后通过free()
间接调用freeSelected (xml.c:369)
。顶部会告诉您有关无效free()
的信息,而最后一部分会告诉您有关原始有效free()
的内容。
它向您展示了三个单独的错误上下文。原始free()
来电被识别为:
freeSelected (xml.c:369)
;
freeSelected (xml.c:370)
;以及
freeSelected (xml.c:369)
再次。
是:
if (selected->father) xmlFree((xmlChar *) selected->father);
if (selected->grandfather) xmlFree((xmlChar *) selected->grandfather);
无效的free()
来电被识别为:
freeChild (xml.c:286)
;
freeChild (xml.c:287)
;以及
freeSpouse (xml.c:308)
是:
xmlFree((xmlChar *) node->father);
xmlFree((xmlChar *) node->grandfather);
xmlFree((xmlChar *) node->husband);
这里发生的情况是,您free()
是一系列具有互惠关系的节点,例如,当您在node->father
中免费xml.c:286
时包含指向您之前已在xmlChar *
中释放的xml.c:369
的指针。
如果没有您正在使用的数据文件并且能够运行该程序,那么很难具体化,但通常在这种情况下您基本上有两种选择:
在调用 所有你的xmlFree()
调用后,调用NULL
指针,如下所示:
if ( node->father ) {
xmlFree((xmlChar *) node->father);
node->father = NULL;
}
以便下次您在同一指针上调用xmlFree()
时,它会发现它NULL
并跳过它。
问题在于,如果您有两个指向同一内存的不同指针,这对您来说不太可能。如果在一个节点中将指针设置为NULL
,则不会将另一个节点中的指针设置为NULL
,它仍将指向您已释放的数据。因此,NULL
检查将检查错误的指针,并且您仍然会收到无效的free()
。你可以通过使用指针指针解决这个问题,但它会变得混乱,实际上,你最好的选择是:
确保您虔诚地复制所有内容(此处,可能是通过xmlStrdup()
),以确保您完全避免在不同节点中指针指向同一事物的情况。这样,你可以愉快地释放所有东西,而不必担心意外地放松两次。