sisoputnfrba / foro

Foro de consultas para el trabajo práctico
151 stars 7 forks source link

Manejo de memoria, puntero que apunta a contenido de puntero #971

Closed ivigilante closed 6 years ago

ivigilante commented 6 years ago

Hola! Quizás me este mareando con este tema, pero me surgió una duda. En este momento en mi TP, estoy recibiendo un puntero a void. (void* puntero1) Ahora, yo para evitarme el hecho de tener que castearlo siempre que lo uso en mi función, pensé en hacer OTRO puntero y que este apunte al contenido de puntero1

tipoDato ptr2; ptr2 = *ptr1;

Con esto pensé que el puntero estaría apuntando a la memoria que el puntero1 tenía reservada y en caso de hacer free de ptr1 o de ptr2 sería igual. Para evitar problemas con el ptr1, pensé hacer

ptr1 = NULL;

así ya no apuntaba a dicha sección de memoria.

Estuve revisando apuntes de la cursada de algoritmos, buscando en internet y haciendo pruebas en Eclipse, pero no me puedo sacar la duda. Esto es realmente así? O estoy obligado a hacer mallocs y memcpy?

Quizás la solución más sencilla sea castearlo siempre, pero quería saber realmente si estaba entendiendo como funcionaba.

Desde ya, muchas gracias! Saludos

tferraro commented 6 years ago

Entiendo tu razonamiento, pero no entiendo la duda :stuck_out_tongue:

Hacer *ptr2 = *ptr1; es el equivalente a decir "asigná lo que hay en la posición de memoria ptr1 a porción de memoria a la que apunta prt2". El problema es, que si son de tipos diferentes, los tamaños son diferentes, y por buenas prácticas, el compilador suele avisarte suponiendo que te estás mandando una macana.

Saliendo de eso, el único inconveniente es que estás literalmente haciendo esto: image

No parece muy lógico verdad? Especialmente que, si el tamaño que lo que estás queriendo meter en ptr2 es más grande que el tamaño pedido, lease, int -> char, que pasaría?

Memcpy te soluciona un poco eso porque te pide el tamaño de lo que vas a copiar (especialmente si querés copiar más de 1 elemento, un "array"), y ni hablar de que malloc tenés, la pregunta es, porque?

ivigilante commented 6 years ago

Gracias por la rápida respuesta, lo que pasa es que yo hice una función genérica que recibe un void, pero una vez que lo recibe, me fijo que es y ahí es cuando quiero asignarle a ptr1, ptr2. ptr2 sería del mismo tipo que ptr1, pero como la función recibe void, tengo que castearlo todo el tiempo para poder acceder a la estructura que yo ya sé que tiene ptr2 (sé que la tiene porque verifico con un header que tiene la estructura).

Al verificar con el header que ptr2 efectivamente es mismo tipo que ptr1, estaría bien? No entendí la última oración en especial:

y ni hablar de que malloc tenés, la pregunta es, porque?

Por qué tengo malloc? Porque previamente lo estoy recibiendo de otro proceso lo que hay en ptr2. Si hay algo que no se entendió decime y de última te copio un cachito del código y listo.

PD: El header de la estructura vendría siendo un int identificador que me sirve para saber que estructura llego a mi función.

EDIT: Dato importante que olvide mencionar, al asignar estoy casteando tipoDato* ptr2; *ptr2 = *(tipoDato*)ptr1; Así sería, perdón, se me pasó eso

tferraro commented 6 years ago

Perdón por colgar, estuve un poco ocupado a la tarde.

Partamos esto en 2 respuestas, vamos con la primera parte: la metáfora del martillo de arriba:

Podes hacer lo que estás diciendo, pero necesitás que pasa en tu segundo puntero, haya memoria reservada, no te "hace una copia de la memoria", solamente lee y pega el valor a donde referencia el puntero en la posición de memoria del otro puntero. Memcpy hace exactamente eso pero te asegurás que no te pasás del tamaño reservado de memoria. No vale recortarle las puntas al cuadrado, el SO te las va a recortar a vos y te saca del medio si te pasás (en el mejor de los casos).

Además, tenés el problema que solo vas a poder copiar una unidad del elemento que referencia el puntero, si es, por ejemplo, un array de char, se va a copiar el valor del primero solamente.

Ahora vamos por la segunda: el malloc

Como te dije, necesitas que la memoria donde vos escribas en ptr2 ya esté reservada, sino te arriesgás a comportamiento indefinido (y posiblemente un SegFault), de ahí que no podés prescindir de malloc.

Tendrías que tener algo como:

int* ptr1 =  malloc(sizeof(int));
int* ptr2 =  malloc(sizeof(int));

*ptr1 = 2;
*ptr2 = *ptr1;

Pero guarda, que si son tipos diferentes, te arriesgas al problema que comentaba en la parte 1 de la respuesta.

Mi recomendación es, a menos que sean del mismo tipo y sea un único elemento el que vas a querer copiar el valor, usá memcpy + malloc que para algo están.

ivigilante commented 6 years ago

Perfecto! Me imaginé que eso era lo recomendable así que ya lo estuve aplicando. Muchas gracias.