簡體   English   中英

解決K&R書(自引用結構)第6.5章示例中的內存泄漏

[英]Fixing Memory Leaks in Chapter 6.5 Example in the K&R book (Self-Referential Structures)

我在Visual Studio中使用視覺泄漏檢測器,運行程序時它會檢測到一些泄漏。 基本上,程序中存在兩種泄漏,一種是在malloc結構* p上檢測到的,另一種是在其成員中檢測到的(p-> word)。 我閱讀了有關您有關在malloc結構中釋放內存的所有討論。 問題是我似乎找不到可以釋放內存的地方,尤其是當這是遞歸結構時。

這是代碼

#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函數

要解決此問題,請創建一個看起來像您的打印函數的遞歸函數以釋放您的樹。

一個例子 :

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

您可以在treeprint之后將其放在主treeprint

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

在這種情況下,編寫完一個遞歸函數即可釋放樹。 符合此代碼的樣式:

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

請注意,在程序結束時仍可訪問的已分配內存並不是真正的泄漏,因為操作系統會對其進行清理。 這里有些有趣的討論,尤其是這個答案

當然,一旦完成處理,釋放內存是一種很好的方式,但是我會更加關注已分配但現在無法訪問的內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM