无法检测到内存泄漏

问题描述 投票:0回答:1

我写了一个程序来搜索几个文本文件中最长的句子:

/* lngst_sentence_file_competition.c */

#include <stdio.h>
#include <stdlib.h>

enum consts {
    str_len = 5
};

typedef struct tag_item {
    int sentence_length;
    char *sentence;
    struct tag_item *next;
} item;

void free_str_if_it_is_not_lngst(
    char **str, char **lngst_file_str, int *curr_sentence_len,
    int *file_lngst_sentence_len
)
{
    if (*curr_sentence_len <= *file_lngst_sentence_len)
        free(*str);
    else {
        if (*lngst_file_str) {
            free(*lngst_file_str);
            *lngst_file_str = NULL;
        }
        *lngst_file_str = *str;
        *file_lngst_sentence_len = *curr_sentence_len;
    }
    *curr_sentence_len = 0;
    *str = NULL;
}

void find_lngst_sentence_in_next_file(
    FILE *file, char **lngst_file_str, int *lngst_sentence_len
)
{
    char *str = malloc(str_len*sizeof(char));
    int str_mem_size = str_len;
    int c;
    int curr_sentence_len = 0;
    int file_lngst_sentence_len = 0;
    while ((c=fgetc(file)) != EOF) {
        switch (c) {
            case '.':
                str[curr_sentence_len] = '.';
                str[curr_sentence_len + 1] = '\0';
                free_str_if_it_is_not_lngst(
                    &str, lngst_file_str, &curr_sentence_len,
                    &file_lngst_sentence_len
                );
                str = malloc(str_len*sizeof(char));
                str_mem_size = str_len;
                /* falls through */
            case '\n':
            case '\t':
                continue;
        }
        curr_sentence_len++;
        if (curr_sentence_len+1 == str_mem_size) {
            str = realloc(str, str_mem_size + str_len);
            str_mem_size += str_len;
        }
        str[curr_sentence_len - 1] = c;
    }
    free_str_if_it_is_not_lngst(
        &str, lngst_file_str, &curr_sentence_len, &file_lngst_sentence_len
    );
    if (*lngst_sentence_len < file_lngst_sentence_len)
        *lngst_sentence_len = file_lngst_sentence_len;
}

int main(int argc, char **argv)
{
    FILE *file;
    item *first = NULL;
    int lngst_sentence_len = 0;
    int i;
    for (i=1; i < argc; i++) {
        char *str = NULL;
        file = fopen(argv[i], "r");
        if (!file) {
            perror(argv[i]);
            exit(1);
        }
        find_lngst_sentence_in_next_file(file, &str, &lngst_sentence_len);
        printf("%s\nString length is %d.\n", str, lngst_sentence_len);
        /* add_new_element_to_linked_list(&first, str); */
    }
    /* print_sentences(first); */
    return 0;
}

我还写了一个小测试文件

test.txt
:

a.
ab.
abc.

我使用 Valgrind 运行我的程序:

valgrind --tool=memcheck --leak-check=full -s ./lngst_sentence_file_competition test.txt

Valgrind 产生以下输出:

==359271== 
abc.
String length is 3.
==359271== 
==359271== HEAP SUMMARY:
==359271==     in use at exit: 477 bytes in 2 blocks
==359271==   total heap usage: 7 allocs, 5 frees, 5,612 bytes allocated
==359271== 
==359271== 5 bytes in 1 blocks are definitely lost in loss record 1 of 2
==359271==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==359271==    by 0x109389: find_lngst_sentence_in_next_file (lngst_sentence_file_competition.c:53)
==359271==    by 0x1094F4: main (lngst_sentence_file_competition.c:87)
==359271== 
==359271== LEAK SUMMARY:
==359271==    definitely lost: 5 bytes in 1 blocks
==359271==    indirectly lost: 0 bytes in 0 blocks
==359271==      possibly lost: 0 bytes in 0 blocks
==359271==    still reachable: 472 bytes in 1 blocks
==359271==         suppressed: 0 bytes in 0 blocks
==359271== Reachable blocks (those to which a pointer was found) are not shown.
==359271== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==359271== 
==359271== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

有人能看到内存泄漏的根源吗?

在我看来,我已经正确释放了所有分配的内存。

c valgrind
1个回答
0
投票

在您的总使用堆中,您有 7 次分配和 5 次释放,剩下的最后两个与文件指针 filestr 指针相关。

在for循环开始时,你定义一个char指针为空,完成for循环后仍然会有一个指针未被使用,因此,在printf()之后放置一个free(str),这样每次新的交互您将分配和释放该内存空间。此外,关闭文件指针,因为这会分离用于读取它的内存空间。

int main(int argc, char **argv)
    {
        FILE *file;
        item *first = NULL;
        int lngst_sentence_len = 0;
        int i;
        for (i=1; i < argc; i++) {
            char *str = NULL;
            file = fopen(argv[i], "r");
            if (!file) {
                perror(argv[i]);
                exit(1);
            }
            find_lngst_sentence_in_next_file(file, &str, &lngst_sentence_len);
            printf("%s\nString length is %d.\n", str, lngst_sentence_len);
            /* add_new_element_to_linked_list(&first, str); */
            free(str);
            fclose(file);
        }
        /* print_sentences(first); */
        return 0;
    }
© www.soinside.com 2019 - 2024. All rights reserved.