【问题标题】:Valgrind leak not sure where it is?Valgrind 泄漏不确定它在哪里?
【发布时间】:2014-06-30 19:32:51
【问题描述】:

不确定这 16 个字节到底在哪里没有被释放。任何关于最后免费在哪里的想法都会很棒。我对 C 和一般编程也很陌生。

==23862== HEAP SUMMARY:
==23862==     in use at exit: 16 bytes in 1 blocks
==23862==   total heap usage: 25 allocs, 24 frees, 2,146 bytes allocated
==23862== 
==23862== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==23862==    at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==23862==    by 0x400B5D: read_from_file (sorting.c:145)
==23862==    by 0x40093F: main (sorting.c:73)
==23862==
==23862== LEAK SUMMARY:
==23862==    definitely lost: 16 bytes in 1 blocks
==23862==    indirectly lost: 0 bytes in 0 blocks
==23862==      possibly lost: 0 bytes in 0 blocks
==23862==    still reachable: 0 bytes in 0 blocks
==23862==         suppressed: 0 bytes in 0 blocks

但是,如果我删除第 146 行,所有内容都会被释放,并且我从 4 个上下文中得到四个错误,说条件跳转或移动取决于未初始化的值。

==31575== Conditional jump or move depends on uninitialised value(s)
==31575==    at 0x400E31: length (sorting.c:238)
==31575==    by 0x400C7D: bubble_sort (sorting.c:186)
==31575==    by 0x4009B8: main (sorting.c:80)
==31575== 
==31575== Conditional jump or move depends on uninitialised value(s)
==31575==    at 0x400DF3: display (sorting.c:225)
==31575==    by 0x4009FC: main (sorting.c:83)
==31575== 
==31575== Conditional jump or move depends on uninitialised value(s)
==31575==    at 0x4A063A3: free (vg_replace_malloc.c:446)
==31575==    by 0x400B2F: destroy (sorting.c:138)
==31575==    by 0x400A08: main (sorting.c:85)
==31575== 
==31575== Conditional jump or move depends on uninitialised value(s)
==31575==    at 0x400B41: destroy (sorting.c:134)
==31575==    by 0x400A08: main (sorting.c:85)

我的代码是:

typedef struct Data_ {

    char *name;
    struct Data_ *nextData;

} Data;

int main(int argc, char **argv)
{
    Data *head = NULL;
    const int size = atoi(argv[2]);
    head = read_from_file(argv[1], size); //line 73
    head = bubble_sort(head);
    destroy(head);
    head = NULL;
    return 0;
}

Data* read_from_file(const char *file, const int size)
{
    Data *head = malloc(sizeof(Data)); //line 145
    head = NULL; //line 146

    FILE* in;
    in = fopen(file,"r");

    if(file == NULL)
    {
        printf("Unable to open %s\n",file);
        exit(1);
    }

    char name[MAX_STR_LEN];
    int i = 0;
    for(;i<size;i++)
    {
        fscanf(in,"%s", name);
        push(&head,name);
    }
    fclose(in);
    return head;
}

void destroy(Data* list)
{
    Data *current = list;
    Data *needs_freeing;

    while(current)
    {
        needs_freeing = current;
        current = current->nextData;
        free(needs_freeing->name);
        free(needs_freeing);
    }
}

void push(Data **head, char *name)
{
    Data *new = malloc(sizeof(Data));
    new->name = malloc(sizeof(char)*MAX_STR_LEN);

    if(new)
    {
        strcpy(new->name, name);
        new->nextData = *head;
        *head = new;
    }
}

Data* bubble_sort(Data *list)
{
    Data *current;
    Data *previous;
    char temp[MAX_STR_LEN];

    int list_length = length(list);
    int i, j;
    for(i=1;i<list_length;i++)
    {
        previous = list;
        current = previous->nextData;
        for(j=0;j<list_length-2;j++)
        {
            if(strcmp(previous->name, current->name) > 0)
            {
                previous = swap(previous, current);
            }
            previous = previous->nextData;
            current = current->nextData;
        }
    }
    return list;
}

Data* swap(Data *left, Data *right)
{
    char temp[MAX_STR_LEN];

    strcpy(temp, left->name);
    strcpy(left->name, right->name);
    strcpy(right->name, temp);
    return left;
}

void display(Data *list)
{
    FILE* file;
    file = fopen("out.txt", "w");
    if(file == NULL)
    {
        printf("Unable to write to file\n");
        exit(1);
    }
    while(list->nextData != NULL)
    {
        fprintf(file,"%s\n",list->name);
        list = list->nextData;
    }
    fclose(file);
}


int length(Data* list)
{
    int count = 0;
    Data* current = list;
    while(current)
    {
        current = current->nextData;
        ++count;
    }
    return count;
}

【问题讨论】:

  • 您没有发布导致未初始化值错误的代码的某些相关部分。此外,name 在函数范围内声明。这也可能很危险,除非 push 是您自己的函数,类似于 memcpy
  • 你能指出其他错误的行号吗?
  • valgrind 也有一个函数可以找到未初始化值的来源,但我不记得它是什么了。
  • 我想通了,或者@JonathanLeffler 还是感谢了。这是一个愚蠢的问题。
  • 请注意,在push() 中,您有:Data *new = malloc(sizeof(Data)); new-&gt;name = malloc(sizeof(char)*MAX_STR_LEN);,然后您测试new 是否已分配。测试为时已晚。您还应该检查new-&gt;name 是否已成功分配。另外,我建议避免在 C 中使用 C++ 关键字,new 是 C++ 关键字。 (不是每个人都同意“避免在 C 中使用 C++ 关键字”,但我认为这是值得的。)

标签: c malloc valgrind free


【解决方案1】:
Data *head = malloc(sizeof(Data)); //line 145
head = NULL; //line 146

这是内存泄漏。您为大小为sizeof (Data) 的对象分配内存,但随后您覆盖了指针。此外,如果您打算在*head 中读取或写入,那么在不使用分配的对象的情况下使指针无效是没有意义的。

【讨论】:

  • 是的,没错,但后来我删除了那行,一切都被释放了,但我收到四个错误,说条件跳转或移动取决于未初始化的值。
  • @user2930353 您还有其他问题,但您没有放置完整的测试用例。
  • @user2930353:也许你想要的是Data *head = calloc(1, sizeof(*head)); 或者head-&gt;name = NULL: head-&gt;nextData = NULL;。这两个都初始化分配的内存,这将防止您提到的其他问题(或者这样做的机会很大)。
  • 是的,有效@JonathanLeffler 很抱歉让一个琐碎的问题变得如此复杂
猜你喜欢
  • 2014-04-02
  • 1970-01-01
  • 2015-10-22
  • 2013-12-24
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多