PlayHardGoPro
PlayHardGoPro

Reputation: 2923

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:

Upvotes: 0

Views: 3110

Answers (3)

PJTraill
PJTraill

Reputation: 1420

Peter Schneider has rightly pointed out that elemento* novo = malloc(sizeof(elemento*)) only allocates enough room for a pointer (because that’s what elemento* is); in this situation there are two common idioms, either of which does fine here:

  • elemento* novo = malloc(sizeof(elemento))
  • elemento* novo = malloc(sizeof(*novo))

And of course you need to take Jongware’s advice too!

Upvotes: 1

Jongware
Jongware

Reputation: 22447

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));.

Upvotes: 1

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16017

With elemento* novo = malloc(sizeof(elemento*)); you malloc only space for a pointer but then treat it as space for a struct. That overwrites book keeping information on the heap.

Upvotes: 2

Related Questions