Search code examples
cpointersrealloc

Realloc Invalid Pointer. Aborted (core dumped)


     *MyFile.h*

        typedef char* dado_t;
        typedef struct elemento elemento;
        typedef struct lista2 lista2;  

    *MyFile.c*

    struct elemento{
        dado_t str;
        elemento* ant;
        elemento* prox;
    };

    struct lista2{
        elemento* primeiro;
        elemento* ultimo;
        elemento* corrente;
    };

    void_insert(lista2* l, dado_t d){
       elemento* novo = malloc(sizeof(elemento*));
       novo->str = malloc(strlen(d) * sizeof(char));
       novo->str = d;
       l->corrente = novo;
       l->primeiro = novo;
       l->ultimo = novo;
       novo->prox = NULL;
       novo->ant = NULL;

    }

dado_t replace(lista2* l, dado_t d){
   dado_t retorno = malloc(strlen(corrente->str) * sizeof(dado_t));
   retorno = corrente->str;

   corrente->str = realloc(corrente->str, strlen(d) * sizeof(char));
   l->corrente->str = d;
   return retorno;
}

Why am I getting this error ? Since myel->str is a pointer that has been allocated with malloc(). Why the error ? I'm using an temporary element* to be prevented if an error happen with realloc()

Obs:


Solution

  • The type dado_t is a char *, which initially points to nothing (I mean, not NULL but some random value). You correctly allocate some memory for it in

    novo->str = malloc(strlen(d) * sizeof(char));
    

    which has one tiny error: a C string of length d needs a single byte more memory for the terminating zero. So change this to

    novo->str = malloc(strlen(d)+1);
    

    Two notes here: sizeof(char) is guaranteed to be 1 (I think it's in the specifications; then again, it does no harm, and maybe you want to make sure you have the syntax right when allocating ints or other larger types).
    Second, most standard libraries have a function that does exactly this: strdup. All you need to do is call it with your string address, it does the +1 part itself.

    However, the next line is a more serious error:

    novo->str = d;
    

    In C you cannot "assign" one string to another this way. If you would want to do that, you would assign the address of one string to another. Which may lead to unforeseen problems, such as 'assigning' the address a constant string (which is valid but then you cannot modify it), or, worse, a string that is created inside a function on the 'local' stack.

    In this case, you want to store a full copy of the string d from the function's argument, so you would use

    strcpy (novo->str, d);
    

    Do not forget that this pointer will be "lost" if you ever free the structure novo. A "lost" pointer is a block of memory that you allocated earlier (in the string malloc line) but no longer have a valid variable pointing to. So when freeing your elemento lists, call free(xx->str) first.

    If you make sure that the str element is always set to NULL as soon as you create a new elemento structure, you can safely call free for the string even though it may be NULL; free can handle that. As it is, you seem to always assign a value, so it's not a case here, but in general I find it safe to explicitly clear out a newly created structure, for example with memset (novo, 0, sizeof(elemento));.