Corrigir erro de Ponteiro Inválido Livre em C

  1. Não free Ponteiros que apontam para locais de memória não-dinâmica
  2. Não free de apontadores que já tenham sido libertados

Este artigo irá introduzir múltiplos métodos sobre como corrigir o erro de ponteiro inválido “livre” em C.

Não free Ponteiros que apontam para locais de memória não-dinâmica

A chamada de função free só deve ser utilizada para desalocar a memória a partir das indicações que tenham sido devolvidas pelas funções malloc, calloc, ou realloc. O código seguinte mostra o cenário em que ao ponteiro char* é atribuído um valor retornado da chamada malloc, mas mais tarde no bloco else, o mesmo ponteiro é reatribuído com uma string literal. Isto significa que a variável c_str aponta para o local que não é uma região de memória dinâmica; assim, não é permitido passar para a função free. Como resultado, quando o próximo exemplo é executado, e o programa atinge a chamada de função free, é abortado, e o erro free(): ponteiro inválido é exibido.

Note-se que não se deve reatribuir os apontadores a localizações de memória dinâmica com endereços diferentes, a menos que ainda existam outras variáveis do ponteiro que apontem para a localização original. Finalmente, só se deve chamar a função free em apontadores que apontem para a memória de pilha.

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

int main(int argc, const char *argv[]) {
    char *c_str = NULL;
    size_t len;

    if (argc != 2) {
        printf("Usage: ./program string\n");
        exit(EXIT_FAILURE);
    }

    if ((len = strlen(argv[1])) >= 4) {
        c_str = (char *)malloc(len);

        if (!c_str) {
            perror("malloc");
        }

        strcpy(c_str, argv[1]);
        printf("%s\n", c_str);
    } else {
        c_str = "Some Literal String";
        printf("%s\n", c_str);
    }
    free(c_str);

    exit(EXIT_SUCCESS);
}

Não free de apontadores que já tenham sido libertados

Outro erro comum quando se utiliza a memória dinâmica é chamar a função free nos ponteiros que já foram libertados. Este cenário é mais provável quando existem múltiplas variáveis de apontadores apontando para a mesma região de memória dinâmica. O seguinte código de amostra demonstra um desses casos possíveis, em que a mesma localização é libertada em âmbitos diferentes.

Note-se que este exemplo é um único programa curto de ficheiro, e será fácil diagnosticar um problema como este, mas nas bases de código maiores, poderá ser difícil rastrear a fonte sem programas de inspectores externos que façam análises estáticas.

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

int main(int argc, const char *argv[]) {
    char *c_str = NULL;
    size_t len;

    if (argc != 2) {
        printf("Usage: ./program string\n");
        exit(EXIT_FAILURE);
    }
    char *s = NULL;

    if ((len = strlen(argv[1])) >= 4) {
        c_str = (char *)malloc(len);
        s = c_str;

        if (!c_str) {
            perror("malloc");
        }

        strcpy(c_str, argv[1]);
        printf("%s\n", c_str);
        free(c_str);
    } else {
        c_str = "Some Literal String";
        printf("%s\n", c_str);
    }
    free(s);

    exit(EXIT_SUCCESS);
}

Artigo relacionado - C Pointer

  • Usar Apontador Amperímetro e Notação em C