修复第5章中的内存泄漏K& R书中的示例(自引用结构)

时间:2013-07-04 06:06:06

标签: c memory-leaks

我在visual studio中使用视觉泄漏检测器,当我运行程序时它会检测到一些泄漏。基本上,程序中存在两个泄漏,一个在malloc'd结构* p上检测到,另一个在其成员中检测到(p->字)。 我阅读了关于在malloc'd结构中释放内存的讨论。问题是我似乎无法找到一个可以释放内存的地方,尤其是当这是一个递归结构时。

这是代码

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include <stdlib.h>
#include <vld.h>

#define MAXWORD 100

struct tnode { /*the tree node */
    char *word; /* points to itself */
    int count; /* number of occurences */
    struct tnode *left; /* left child */
    struct tnode *right; /* right child */
};


struct tnode *addtree (struct tnode *, char *);
struct tnode *talloc(void);
void treeprint (struct tnode *);
char *strdupli (char *s);
int getword (char *, int);
void strcopy (char *, const char *);

int main(void)
{
    struct tnode *root;
    char word[MAXWORD];

    root = NULL;
    while(getword(word, MAXWORD) != EOF)
        if( isalpha (word[0]))
            root = addtree(root, word);
        treeprint(root);
        return 0;
}



int getword(char *word, int lim)
{
    int c, getch(void);
    void ungetch(int);
    char *w = word;

    while(isspace(c = getch()))
        ;
    if(c != EOF)
        *w++ = c;
    if(!isalpha(c)) {
        *w = '\0';
        return c;
    }
    for( ; --lim > 0; w++)
        if(!isalnum(*w = getch())) {
            ungetch(*w);
            break;
        }
    *w = '\0';
    return word[0];

}

struct tnode *addtree (struct tnode *p, char *w)
{
    int cond;

    if (p == NULL) { /* a new word has arrived*/
        p = talloc(); /* make a new node */
        p->word = strdupli(w);
        p->count = 1;
        p->left = p->right = NULL;
    } else if ((cond=strcmp(w, p->word))==0)
        p->count++;
    else if (cond < 0)
    {
        p->left = addtree (p->left, w);
    } else
    {
        p->right = addtree(p->right, w);
    }
    return p;
}

void treeprint (struct tnode *p)
{
    if(p != NULL) {
        treeprint(p->left);
        printf("%4d %s\n", p->count, p->word);
        treeprint(p->right);
    }
}


/* talloc: make a tnode */
struct tnode *talloc(void)
{
    return (struct tnode *) malloc(sizeof(struct tnode));
}

char *strdupli (char *s) /* make a duplicate of s */
{
    char *p;
    p = (char *) malloc (strlen(s) + 1);
    if (p != NULL)
        strcopy(p, s);
    return p;
}

void strcopy (char *s, const char *t)
{
        while ((*s++ = *t++) != '\0')
        ;
}

#define BUFSIZE 100
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */
int getch(void) /* get a (possibly pushed-back) character */
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) /* push character back on input */
{
    if (bufp >= BUFSIZE)
        printf("ungetch: too many characters\n");
    else
        buf[bufp++] = c;
}

你需要看看* addtree功能

2 个答案:

答案 0 :(得分:3)

要解决此问题,请创建一个看起来像打印函数的递归函数来释放树。

一个例子:

void free_tree (struct tnode *p)
{
    if(p != NULL) {
        free_tree(p->left);
        free_tree(p->right);
        free( p->word );
        free( p );
    }
}

您可以在treeprint之后将其放在主页中:

int main(void)
{
    ...
    treeprint(root);
    free_tree( root );
    // ^^^^^^^^^^^^^^^
    return 0;
}

答案 1 :(得分:1)

在这种情况下,你编写了一个递归函数来完成它的释放。符合此代码的风格:

void tfree(struct tnode *p) 
{ 
    if (p != NULL) {
        tfree(p->left);
        tfree(p->right);
        free(p->word);
        free(p);
    }     
}

请注意,在程序结束时仍然可以访问的malloced内存实际上并不是泄漏,因为操作系统会清理它。一些有趣的讨论here,特别是this answer

当然,一旦你完成它就可以释放内存,但是我会更关心分配但现在无法访问的内存。