【问题标题】:Memory Leak even though I'm freeing the calloc即使我正在释放 calloc,也会出现内存泄漏
【发布时间】:2021-11-19 06:55:31
【问题描述】:

我正在编写一个 C 程序,我必须在其中跟踪来自标准输入的重复输入。该程序可以正常运行,但即使我正在释放 calloc,我也遇到了内存泄漏问题。

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

int main(int argc, char* argv[])
{   
    char **words = calloc(1000, sizeof(*words));
    for (int a = 0; a < 1000; ++a)
    {
        words[a] = malloc(50);
    }
    char *input = calloc(1000, sizeof(input));
    
    int count = 0;
    
    while (1)
    {       
        if (fgets(input, 100, stdin) == NULL)
        {
            break;
        }
        else
        {
            words[count] = strdup(input);
            count++;
        }
    }
    
    char *x;
    int ret, repeat = 1, z = 0;
    
    while (z < count - 1)
    {
        x = words[z];
        z++;
        ret = strcmp(x, words[z]);
        
        if (ret == 0)
        {
            repeat++;
        }
        else
        {
            printf("%d %s", repeat, words[z-1]);
            repeat = 1;
        }
        
    }
    printf("%d %s", repeat, words[z]);

    for (int a = 0; a < 1000; ++a)
    {
        free(words[a]);
    }
    free(input);
    
    
    return 0;

}
==2635409==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 8000 byte(s) in 1 object(s) allocated from:
    #0 0x7f349bdfbdc6 in calloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10ddc6)
    #1 0x55b986a362eb in main /common/home/jtg136/Desktop/Homework1/Unique4/uniq.c:8
    #2 0x7f349bb230b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

Direct leak of 250 byte(s) in 5 object(s) allocated from:
    #0 0x7f349bdfbbc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #1 0x55b986a36317 in main /common/home/jtg136/Desktop/Homework1/Unique4/uniq.c:11
    #2 0x7f349bb230b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: 8250 byte(s) leaked in 6 allocation(s).

我曾经将字符串数组格式化为 char *words[1000],但我不得不更改为 calloc,因为前者总是会导致内存泄漏,但现在即使我释放它也不会停止泄漏.我有什么遗漏吗?

【问题讨论】:

  • words[a] = malloc(50); 分配内存。 words[count] = strdup(input); 覆盖先前的分配并丢失指针。所以原来的malloc不能被释放——内存泄漏!不需要第一个malloc,因为strdup 会为您分配新内存。
  • 你在哪里免费words
  • 您对malloccallocstrdup 等的每个呼叫都需要与对free 的相应呼叫相匹配。所以,列个清单。您没有释放words 本身,也没有在用strdup 的结果替换它们之前释放words[a] 的旧值。
  • 删除 malloc[50] 循环并放置 free(words) 解决了问题!奇怪,因为我发誓我以前做过 free(words) 并且由于某种原因它给出了一个错误,但它现在可以工作了。谢谢大家!
  • @Vearaa 引用:“删除 malloc[50] 循环并放置 free(words) 解决了问题!”它可能修复了内存泄漏,但它给你留下了一个“非常奇怪”的程序。

标签: c pointers memory


【解决方案1】:

在 cmets 中已经指出内存泄漏是由于

  1. words 永远不会被释放

  2. words[count] = strdup(input);覆盖words[a] = malloc(50);分配的内存

修复它可以解决内存泄漏,但考虑整个程序结构也很有趣。

为什么要使用strdup

strdup 不是必须的,fgets 可以直接使用。换句话说 - 为什么将 input 读入然后将 input 复制到 words[count] 中?直接读 inot words[count]就好了。

所以不是这个“复杂”的循环。

while (1)
{       
    if (fgets(input, 100, stdin) == NULL)
    {
        break;
    }
    else
    {
        words[count] = strdup(input);
        count++;
    }
}

你可以这样做

while (count < 1000 && fgets(words[count], 50, stdin) != NULL)
{       
    count++;
}

它更简单,你不需要strdup(也不需要input)。

所以你的程序可能是:

#define MAX_WORDS 1000
#define MAX_LEN 50

int main(void)
{   
    char **words = calloc(MAX_WORDS, sizeof(*words));
    for (int a = 0; a < MAX_WORDS; ++a)
    {
        words[a] = malloc(MAX_LEN);
    }
    
    int count = 0;
    
    while (count < MAX_WORDS && fgets(words[count], MAX_LEN, stdin) != NULL)
    {       
        count++;
    }

    ....
    ....


    for (int a = 0; a < MAX_WORDS; ++a)
    {
        free(words[a]);
    }
    free(words);
    
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 2011-04-15
    • 1970-01-01
    • 2020-09-19
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多