1548132==ОШИБКА: средство очистки от утечек: обнаружены утечки памяти

#c #memory-leaks #malloc #dynamic-memory-allocation

Вопрос:

Я запустил автогрейдер в своей программе и получил эту ошибку, но когда я запускаю тот же самый тест вручную, кажется, что он работает нормально. Я не уверен, почему я получаю ошибку только тогда, когда использую автогрейдер. Я новичок в C, и я не понимаю, почему происходит утечка памяти, потому что я освободил все переменные, для которых я использовал malloc. Это показывает мне, какие строки конкретно вызывают ошибку, но я не знаю, как ее исправить, не «испортив» мой код/вывод.

Сообщение об ошибке

Исходный код:

 struct Node* head; //global variable

void Insert(int x){
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    struct Node* ptr = head;
    
    //check if already present
    while(ptr != NULL){
        if(ptr->data == x){return;}
        ptr = ptr->next;
    }
    
    //check if head is greater
    if(head == NULL || head->data > x){
        temp->data = x;
        temp->next = head;
        head = temp;  
    }else{
        ptr = head;
        while(ptr->next != NULL amp;amp; ptr->next->data < x){
            ptr = ptr->next;
        }
        
        temp->data = x;
        temp->next = ptr->next;
        ptr->next = temp;
    }
   
}
void Delete(int x){
    struct Node* temp = head;
    struct Node* prev;
    
    //if head has key
    if(temp != NULL amp;amp; temp->data == x){
        head = temp->next;
        free(temp);
        return;
    }
    
    //find key
    while(temp != NULL amp;amp; temp->data != x){
        prev=temp;
        temp = temp->next;
    }
    
    //if key isnt present
    if(temp == NULL){return;}
    
    //unlink
    prev->next = temp->next;
    
    free(temp);
}
void Print(){
    struct Node* temp = head;
    int c = 0;
    while(temp != NULL){
        c  ;
        temp = temp->next;
    }
    printf("%d :", c);
    
    temp = head;
    while(temp != NULL){
        printf(" %d", temp->data);
        temp = temp->next;
    }
    printf("n");
}

int main(){
    int x;
    char c;
    head = NULL; //empty list
    
    scanf(" %c%d",amp;c,amp;x);
    if(c == 'i'){
        Insert(x);
    }else if(c == 'd'){
        Delete(x);  
    }
    Print();
    while(scanf(" %c%d",amp;c,amp;x)!=EOF){
        if(c == 'i'){
            Insert(x);
        }else if(c == 'd'){
            Delete(x);
        } 
        Print();
    }
    
    return 0;
}
 

Комментарии:

1. Вы допустите утечку переменной temp, когда ptr->данные будут равны x внутри функции вставки. Вы просто возвращаетесь, не освобождая его.

Ответ №1:

Ваша проблема здесь

 void Insert(int x){
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    struct Node* ptr = head;
    
    //check if already present
    while(ptr != NULL){
        if(ptr->data == x){return;}  <--- If this return is executed, temp is not freed
        ptr = ptr->next;
    }
 

Чтобы исправить это, просто переместите malloc его так, чтобы он был после цикла.

 void Insert(int x){
    struct Node* ptr = head;
    
    //check if already present
    while(ptr != NULL){
        if(ptr->data == x){return;}
        ptr = ptr->next;
    }

    struct Node* temp = malloc(sizeof(struct Node));
 

кстати:

  1. Иметь head в качестве глобальной переменной плохую идею
  2. Не приводите значение, возвращаемое malloc

Комментарии:

1. Вы не знаете контекста переменной head, поэтому не знаете, плохая это идея или нет. Вам следует удалить это замечание.

2. @Fredrik нет, нет, нет…. head как глобальная переменная плоха в любом контексте

3. @4386472 удачи в попытке написать код прерывания без глобальных переменных. Или любой встроенный код, если на то пошло. Люди кричат о стигматизации глобальной переменной только потому, что они где-то читали, что это было плохо.

4. @Fredrik Есть случаи, когда необходимы глобальные переменные, но здесь это абсолютно неправильно

5. @Fredrik, ограничив использование всех функций одним связанным списком.