内存泄漏双指针

时间:2013-11-17 07:43:10

标签: c malloc free valgrind

我无法弄清楚我在这里做错了什么。一般来说是valgrind和C的新手,但已设法清理除了这个之外的所有内存泄漏

==8749== HEAP SUMMARY:
==8749==     in use at exit: 880 bytes in 11 blocks
==8749==   total heap usage: 80 allocs, 69 frees, 5,620 bytes allocated
==8749== 
==8749== 400 bytes in 5 blocks are definitely lost in loss record 1 of 2
==8749==    at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8749==    by 0x402B1C: tokenize (tm_utility.c:78)
==8749==    by 0x402E57: load_data (tm_utility.c:188)
==8749==    by 0x400D0A: main (tm.c:57)
==8749== 
==8749== 480 bytes in 6 blocks are definitely lost in loss record 2 of 2
==8749==    at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8749==    by 0x402B1C: tokenize (tm_utility.c:78)
==8749==    by 0x402C97: load_data (tm_utility.c:147)
==8749==    by 0x400D0A: main (tm.c:57)
==8749== 

它涉及这个功能:

char** tokenize(const char* input)
{
    char* str = (char*)strdup(input);
    int count = 0;
    int capacity = 10;
    char** result = malloc(capacity*sizeof(*result)); /*LINE 78*/

    char* tok=strtok(str,",");

    while(1)
    {
        if (count >= capacity)
            result = realloc(result, (capacity*=2)*sizeof(*result));

        result[count++] = tok? strdup(tok) : tok;

        if (!tok) break;

        tok=strtok(NULL,",");
    }

    free(str);
    return result;
}

我可以看到我没有自由的东西,但我无法弄清楚在哪里释放它(调用函数或本地??)以及它究竟是什么我应该释放?

帮助?

由于

编辑:

以下是来自调用函数的代码。我无法弄清楚还有什么我需要自由,尝试了一些不同的东西,但只是让它变得更糟,最后发布在这里。

while (fgets(line, sizeof(line), coinsfile_stream) != NULL)
{

    tokens = tokenize(line);

    for(i=tokens; i && *i; ++i)
    {

        if(y==0)
        {
            tm->coins[x].denomination = atoi(*i);
            y=1;
            x++;
        }
        else
        {
            tm->coins[z].count = atoi(*i);
            y=0;
            z++;
        }
        free(*i);
    }
}

1 个答案:

答案 0 :(得分:3)

tokenize()中调用load_data()的代码似乎负责执行释放。您将分配的空间返回给调用函数。


现在问题中显示了额外的代码,您需要在处理令牌的free(tokens);循环之后添加for。以下代码使用来自valgrind的健康清单运行:

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

char **tokenize(const char *input);

char **tokenize(const char *input)
{
    char *str = (char *)strdup(input);
    int count = 0;
    int capacity = 10;
    char **result = malloc(capacity*sizeof(*result)); /*LINE 78*/

    char *tok = strtok(str, ",\n");

    while (1)
    {
        printf("Found: <<%s>>\n", tok);
        if (count >= capacity)
            result = realloc(result, (capacity *= 2)*sizeof(*result));

        result[count++] = tok ? strdup(tok) : tok;

        if (!tok)
            break;

        tok = strtok(NULL, ",\n");
    }

    free(str);
    return result;
}

int main(void)
{
    char line[1024];
    int x = 0;
    int y = 0;
    int z = 0;

    struct Coin {
        int denomination;
        int count;
    };
    struct Trade {
        struct Coin coins[10];
    };
    struct Trade tm1;
    struct Trade *tm = &tm1;

    while (fgets(line, sizeof(line), stdin) != NULL)
    {
        char **tokens = tokenize(line);

        for (char **i = tokens; i && *i; ++i)
        {
            printf("Token: <<%s>>\n", *i);
            if (y == 0)
            {
                tm->coins[x].denomination = atoi(*i);
                y = 1;
                x++;
            }
            else
            {
                tm->coins[z].count = atoi(*i);
                y = 0;
                z++;
            }
            free(*i);
        }
        free(tokens);
    }
}

数据文件:

12,23
34,45
56,67

示例输出:

Found: <<12>>
Found: <<23>>
Found: <<(null)>>
Token: <<12>>
Token: <<23>>
Found: <<34>>
Found: <<45>>
Found: <<(null)>>
Token: <<34>>
Token: <<45>>
Found: <<56>>
Found: <<67>>
Found: <<(null)>>
Token: <<56>>
Token: <<67>>

注意:我的代码依赖于我正在处理的系统(Mac OS X 10.9 Mavericks; GCC 4.8.2 - 但valgrind在同一平台上托管的古老Linux VM中运行)在被问到时不会崩溃打印空指针指向的字符串。您需要查看while (1)循环;你应该把它改成while (tok != 0)或同等的。完成后,您可以简化循环体;现在有两个零冗余测试。