Duda con realloc

Iniciado por mester, 6 Septiembre 2016, 16:48 PM

0 Miembros y 2 Visitantes están viendo este tema.

mester

Hola.

Nunca he usado la función realloc, y ahora utilizandola me pregunto algunas cosas:
Cuando utilizo la funcion, el compilador me fuerza un poco a que utilize un valor de retorno. Por ello he hecho el siguiente programa:


int main () {
  int *a, *b = (int *) malloc (sizeof (int));

  b[0] = 20;
  a = (int *)realloc (b, 2 * sizeof (int));
  b[1] = 30;

  printf ("%p\n%p\n", &a, &b);

  return 0;
}


Las dudas que me surgen son... ¿El valor de retorno de realloc apunta a la nueva dirección con los datos que contenía el primer argumento (en este caso a[0] debería ser 20 y tendría que tener espacio para un int más)? ¿Que es lo que ocurre si hago free ( b ); y continuo usando a?
Justicia es dar a cada uno lo que se merece

AlbertoBSD

#1
 ¿Que es lo que ocurre si hago free ( b ); y continuo usando a?

al hacer free, el programa marca el segmento de memoria dado como libre y si lo sigues usando podria ser sobreescrito en cualquiero otro momento por otra variable de tu programa.

¿El valor de retorno de realloc apunta a la nueva dirección con los datos que contenía el primer argumento (en este caso a[0] debería ser 20 y tendría que tener espacio para un int más)?


Si el valore regresado es el nuevo, podria ser el mismo o no, sin embargo veo que estas asignando a la variable "a" pero sigues usando "b", en el caso de que te devuelva una direccion diferente, b ya no aputara mas a un rango de memoria "asignado". b continua con una copia vieje del apuntador.

Y en el caso del printf deberia de ser asi:

printf ("%p\n%p\n", a, b);


Por cierto asegurate de Inicializar la variable que le pasas por primera vez a realloc en NULL ya que es posible que contenga basura en la memoria y te marque segment fault
Tengo aqui un video que realice sobre el tema:
[youtube=640,360]https://www.youtube.com/watch?v=iBf7AThP1w8[/youtube]


Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

ivancea96

http://www.cplusplus.com/reference/cstdlib/realloc/

Muy simple. Trata de reservar un bloque de memoria del nuevo tamaño y preserva los datos del bloque anterior.

El retorno es la dirección del nuevo bloque de memoria, así que tienes que guardarlo siempre (igual que haces con malloc). El antiguo bloque, se libera automáticamente, no tienes que hacerlo tú.

Ahora bien, hay 2 casos especiales:
El primero, es que en vez de darte una dirección nueva, te den la misma dirección. Eso significa que simplemente se amplió el tamaño de ese bloque.
El segundo, es que retorne NULL. Eso significa que no se ha podido reservar el bloque que has pedido. El bloque antiguo no e sliberado en este caso, sigue siendo funcional.


Si después del realloc haces free(b), y continuas usando a, pueden pasar varias cosas.
La primera, que b ya no apunte a un bloque de memoria reservado. Esto nunca lo deberías hacer.
La segunda, que a sea NULL, el caso especial. En este caso, tendrás un error.
En caso de que la dirección de los bloques nocambie (el primer caso especial), estarás liberando el bloque, cosa que también será errónea.

En fin, todo esto es supérfluo, y se resume en el segundo párrafo de este mensaje.

mester

Pero, ¿es necesario que use un valor de retorno? Porque perfectamente podría hacer esto:

int main () {
 int *b = (int *) malloc (sizeof (int));

 b[0] = 20;
 realloc (b, 2 * sizeof (int));
 b[1] = 30;

 printf ("%d\t%d\n", b[0], b[1]);

 return 0;
}


¿Habría algún inconveniente?
Justicia es dar a cada uno lo que se merece

AlbertoBSD

#4
Si hay inconveniente ya que si por ejemplo en el realloc se mueve el bloque de memoria a otro lado, b va a seguir con el mismo apuntador.

Esto es

B apunta a 1000 (Direccion de memoria)
Se pide a reelloc que reasigne el espacio para agregar X cantidad adicional a la existente.
Realloc mueve el bloque que estaba en 1000 al bloque 2000 y retorna la nueva dirección de memoria
Si B no se iguala a lo que  devuelva realloc, entonces B seguira apuntado a 1000, si, ahi siguen tus valores anteriores, pero digamos que existe una variable C en la direccion 1003, entonces cuando tu escribas en tu apuntador B en esa posicion, estaras sobreescribiendo la variable C.

Ejemplo en video:

[youtube=640,360]https://www.youtube.com/watch?v=UbX5Qp9nrMk[/youtube]

Para ejemplo esta el siguiente codigo:

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

int main() {
int i = 0;
int *B = NULL,*C = NULL;
B = realloc(B,sizeof(int));
C = realloc(C,sizeof(int));
C[0] = 1000;
printf("El valor de C[0] es %i\n",C[0]);
realloc(B,sizeof(int)*10); //NO SE ACTUALIZA B
while(i < 10) {
B[i] = 1337;
i++;
}
printf("El valor de C[0] es %i\n",C[0]);
}


Salida:


El valor de C[0] es 1000
El valor de C[0] es 1337


Como vemos, por lo menos en mi computadora el valor de C es sobreescrito y termina con Error de segmento, colgandose el programa.



Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

MAFUS

Para ver de forma más clara el tema trata realloc como si estuviera escrito de la siguiente manera:
void* realloc(void* __ptr, size_t __size) {
    void* retval = (void*)malloc(__size);
   
    if(__ptr) {
        memcpy(retval, __ptr, __size);
        free(__ptr);
    }
   
    return retval;
}


realloc es mucho más elaborada pero su funcionamiento básico se puede representar de susodicha forma.