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

#c #memory-leaks #malloc

Вопрос:

Я продолжаю получать следующую ошибку при запуске своей программы: сообщение об ошибке

В нем упоминаются утечки в строках 15, 64 и 110. Я думаю, что ошибка в функции push, но я не вижу, где я мог бы освободить переменную, не вызывая ошибок в моем коде.

Строка 15: struct sNode* new_node = (struct sNode*)malloc(sizeof(struct sNode));

Строка 64: push(amp;stack, exp[i]);

Строка 110: int n = areBracketsBalanced(argv[1]);

Это мой код:

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

// structure of a stack node
struct sNode {
    char data;
    struct sNode* next;
};

void push(struct sNode** top_ref, int new_data);
int pop(struct sNode** top_ref);
void push(struct sNode** top_ref, int new_data){
    struct sNode* new_node = (struct sNode*)malloc(sizeof(struct sNode));

    if (new_node == NULL) {
        printf("Stack overflow n");
        getchar();
        exit(0);
    }

    new_node->data = new_data;
    new_node->next = (*top_ref);
    (*top_ref) = new_node;
}
int pop(struct sNode** top_ref){
    char res;
    struct sNode* top;
    
    if (*top_ref == NULL) {
        printf("Stack overflow n");
        getchar();
        exit(0);
    }else {
        top = *top_ref;
        res = top->data;
        *top_ref = top->next;
        free(top);
        return res;
    }
}

// Returns 1 if character1 and character2 are matching left and right Brackets
bool isMatchingPair(char character1, char character2)
{
    if (character1 == '(' amp;amp; character2 == ')')
        return 1;
    else if (character1 == '{' amp;amp; character2 == '}')
        return 1;
    else if (character1 == '[' amp;amp; character2 == ']')
        return 1;
    else
        return 0;
}

// Return 1 if expression is balanced
int areBracketsBalanced(char exp[]){
    int i = 0;
    struct sNode* stack = NULL;

    while (exp[i]){
        if (exp[i] == '{' || exp[i] == '(' || exp[i] == '[')
            push(amp;stack, exp[i]);

        if (exp[i] == '}' || exp[i] == ')' || exp[i] == ']') {

            if (stack == NULL){
                printf("%d: %cn",i,exp[i]);
                return 0;
            }else if (!isMatchingPair(pop(amp;stack), exp[i])){
                printf("%d: %cn",i,exp[i]);
                return 0;
            }
        }
        i  ;
    }

    if(stack == NULL){
        return 1;
    }else{
        printf("open: ");
        
            while(stack!=NULL){
             int value = pop(amp;stack);
            if(value == '('){
                printf("%c",')');
            }else if(value == '['){
                printf("%c",']');
            }else if(value == '{'){
                printf("%c",'}');
            }
            }
            printf("n");
            while(stack!=NULL){
            pop(amp;stack);
            }
        return 0;
    }
    
}

int main(int argc, char* argv[]){
    if(argc>1){
        int n = areBracketsBalanced(argv[1]);
        if(n==0){
            return EXIT_FAILURE;
        }else if(n==1){
            return EXIT_SUCCESS;
        }   
    }
    
    //return 1;
}
 

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

1. @TedLyngmo Я обновил код, надеюсь, это облегчит его понимание.

2. Если скобки не сбалансированы, вы возвращаетесь, areBracketsBalanced не открывая остальную часть стека.

3. @Barмар Я в замешательстве, должен ли я вытащить остальную часть стека перед возвращением?

4. Да, если вы хотите предотвратить утечку памяти. У вас может быть просто clear() функция, которая опустошает стек.

5. @Barmar Я отредактировал код, как вы предложили, и он исправил пару других ошибок, но эта все еще сохраняется. Я не понимаю, почему.

Ответ №1:

Вы должны убедиться, что все пути через areBracketsBalanced() пустой стек будут возвращены. Ты упускаешь это дело:

             }else if (!isMatchingPair(pop(amp;stack), exp[i])){
                printf("%d: %cn",i,exp[i]);
                while (stack != NULL) {
                    pop(amp;stack);
                }
                return 0;
            }
 

Поскольку вы делаете это из нескольких мест, я рекомендую определять clear(amp;stack) функцию вместо того, чтобы каждый раз писать цикл.

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

1. О, в этом есть смысл, большое вам спасибо, теперь это работает.