如何在valgrind报告中找出“Invalid Free()”错误的原因

时间:2014-11-16 17:42:40

标签: c memory-management valgrind

我编写了一个xml编辑器,可以在没有警告或错误的情况下编译好,并且运行时不会出现内存泄漏。但是当我运行valgrind并且无法弄清楚导致它的原因时,我一直收到此错误Invalid Free()

我认为它可能与在null或释放指针上运行free命令有关但我无法指出它?是什么导致了它,我如何从报告中得知?

(这是我的完整代码,抱歉有点长)

xml.h

#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

xml.c

#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

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)

1 个答案:

答案 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的指针。

如果没有您正在使用的数据文件并且能够运行该程序,那么很难具体化,但通常在这种情况下您基本上有两种选择:

  1. 在调用 所有你的xmlFree()调用后,调用NULL指针,如下所示:

    if ( node->father ) {
        xmlFree((xmlChar *) node->father);
        node->father = NULL;
    }
    

    以便下次您在同一指针上调用xmlFree()时,它会发现它NULL并跳过它。

    问题在于,如果您有两个指向同一内存的不同指针,这对您来说不太可能。如果在一个节点中将指针设置为NULL,则不会将另一个节点中的指针设置为NULL,它仍将指向您已释放的数据。因此,NULL检查将检查错误的指针,并且您仍然会收到无效的free()。你可以通过使用指针指针解决这个问题,但它会变得混乱,实际上,你最好的选择是:

  2. 确保您虔诚地复制所有内容(此处,可能是通过xmlStrdup()),以确保您完全避免在不同节点中指针指向同一事物的情况。这样,你可以愉快地释放所有东西,而不必担心意外地放松两次。