Problema con realloc funciones y punteros a estructuras [RESUELTO]

Iniciado por Xargam, 2 Junio 2018, 06:26 AM

0 Miembros y 1 Visitante están viendo este tema.

Xargam

Hola gente estoy volviendome loco con  realloc.... Veo que corrompe datos.. Declare una estructura, luego cree un puntero dinamico a ella con malloc. El problema es que si yo paso el puntero a una funcion y en la funcion hago realloc del puntero los datos se corrompen.... por que???????????? Por que si uso realloc con un dato que no es de la funcion mi programa funciona mal¨???

Ejemplo:



#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define MOVFILE "movies.bin"


typedef struct
{
   char titulo[50];
   int duracion;

} eMovie ;

int x(eMovie* movie);
void y(eMovie* movie, int tam);

int main()
{

   eMovie* movies = (eMovie*) malloc(sizeof(eMovie));
   int index = x(movies);
   index++;
   y(movies,index);
   free(movies);
   return 0;
}


int x(eMovie* movie)
{
   int salir = 0;
   int moves = 0;
   while(salir != 27)
   {
       printf("\nTITULO: ");
       scanf("%s", (movie + moves)->titulo);
       printf("\nDURACION: ");
       scanf("%d", &(movie + moves)->duracion);
       printf("SALIR? esc:");
       salir = getche();
       if(salir != 27)
       {
           moves++;
           movie =(eMovie*) realloc(movie,sizeof(eMovie)*(moves+1) );
       }
   }
   free(movie);
   return moves;
}

void y(eMovie* movie, int tam)
{
   for(int i = 0; i < tam; i++)
   {
       printf("\n\nTITULO: %s\n", (movie + i)->titulo);
       printf("DURACION: %d\n", (movie + i)->duracion);
   }
}


Como ven el puntero a movie se pasa a una funcion y alli se hace el realloc pruebenlo, el string se cambia... Al imprimirse...

SrMcLister

Buenas Xargam.
Para que se pueda probar tu código se necesita la estructura declarada, en general, todo el código en si.
Me gustaría ayudarte pero sin la estructura no va a poder ser.
Un Saludo.
PD: El código ponlo entre etiquetas de code, para que sea más legible ;D
Código (cpp) [Seleccionar]

return((u.areHappy() && u.knowIt()) ? u.clapYourHands() : u.goFuckYourself());

Xargam

Ya le agregue las etiquetas, el define no sirve, en realidad esto trbajaba con archivos y debido al problema que me genera realloc reduci el codigo para mostrarlo.

MAFUS

Línea 47. ¿Para qué liberas movie? Lo sigues necesitando una vez fuera de la función.
Línea 29. El argumento de x debería ser un puntero a puntero ya que realloc te puede reasignar la dirección del array dinámico. Si pasas solo el puntero éste será copiado, debido a que los argumentos se pasan por valor, y aunque se modifique cuándo salgas de la función no verás ese cambio.

srWhiteSkull

#4

...

int main()
{

   eMovie* movies = (eMovie*) malloc(sizeof(eMovie));
...

Lo que hagas aquí, se queda ahí. Lo que vengo a decirte, como el caso de otro hilo similar y reciente, es que C no es C++, y la única forma que tienes para modificar el puntero es retornando el nuevo puntero en la función x o usando un puntero global.

Cuando pasas por referencia pasa eso precisamente, que pasas por referencia, y lo único que puedes hacer con eso es modificar el contenido existente en esa dirección, pero no puedes asignar otro puntero, porque lo que tienes en la función es una copia del puntero que usa la misma referencia que le pasas. Por eso, insisto, retorna el nuevo puntero.

Acostumbra a NO hacer eso :

...
       scanf("%s", (movie + moves)->titulo);
       printf("\nDURACION: ");
       scanf("%d", &(movie + moves)->duracion);
       printf("SALIR? esc:");
...

Usa variables y luego pásalo luego al objeto. Para pasar un char[] a otro char[] usa el memcpy(). Si tienes pensado usar movie como un array, que no sería lo adecuado, úsalo como un array, no uses aritmética de punteros de esa forma. Ejemplo:

...
       scanf("%s", movie[moves].titulo);
       printf("\nDURACION: ");
       scanf("%d", &duracion);
       movie[moves].duracion=duracion;
       printf("SALIR? esc:");
...


Si vas a retornar el puntero para usarlo como te dije, no liberes el puntero antes de devolverlo (el free() ese dentro de la función x). Libera la memoria en el main o función principal.

Aquí lo mismo que te dije antes...

void y(eMovie* movie, int tam)
{
   for(int i = 0; i < tam; i++)
   {
       printf("\n\nTITULO: %s\n", (movie + i)->titulo);
       printf("DURACION: %d\n", (movie + i)->duracion);
   }
}

Usa un array.. ... verás más legible el código.

  movie[i].titulo
  movie[i].duracion


Y si no, como antes le dije al otro, si quieren trabajar con punteros de forma más flexible y segura usen C++.

Xargam

Cita de: MAFUS en  2 Junio 2018, 14:40 PM
Línea 47. ¿Para qué liberas movie? Lo sigues necesitando una vez fuera de la función.
Línea 29. El argumento de x debería ser un puntero a puntero ya que realloc te puede reasignar la dirección del array dinámico. Si pasas solo el puntero éste será copiado, debido a que los argumentos se pasan por valor, y aunque se modifique cuándo salgas de la función no verás ese cambio.
Hola muchisimas gracias ppr tu respuesta,ya pude resolver el problema,pero quisiera saber mas acerca del por que no se puede  pasar solo el puntero. Osea si haces realloc reservas mas espacio en memoria,por que los datos deaaparecen??? Podrias ser mas especiico

MAFUS

Realloc funciona más o menos de esta forma:
Primero asigna un trozo de memoria del tamaño que le indiques, después copia el contenido de de tu viejo puntero al nuevo, libera el viejo y devuelve el nuevo.

Y cómo el puntero cambia, el que no pases por referencia un puntero (un puntero a puntero) no verás los cambios que se han hecho y además tendrás un puntero suelto porque realloc te lo ha liberado.

srWhiteSkull

#7
Cita de: MAFUS en  3 Junio 2018, 08:21 AM
Y cómo el puntero cambia, el que no pases por referencia un puntero (un puntero a puntero) no verás los cambios que se han hecho y además tendrás un puntero suelto porque realloc te lo ha liberado.
Buff gracias por recordármelo,

Claro, la otra opción Xargam es lo que comenta MAFUS, que en vez de retornar (con un return) el puntero o usar un puntero global, es usando el puntero a puntero, que es simplemente definir el puntero en el argumento de la función de x con dos asteriscos (**) y tratarlo en la función así (*movie)[moves] o así (*(*movie+moves)). Corrígeme MAFUS si me equivoco.

Xargam