Anuncios Google

Punteros tocanarices [SOLUCIONADO]

Buenas,

me he pasado media tarde buscando tutos sobre punteros, y no he conseguido aclararme (y fueron tutos y tutos...).

Soy capaz de discernir que un puntero es un tipo de variable que apunta a un lugar determinado de la memoria, que * básicamente lleva información a esa dirección de memoria y & trae la variable de la memoria para ser usada. Mi problema no es crear punteros, mi problema no es usarlos (al menos de momento). Mi problema es lo que técnicamente dieron por denominar "liberar punteros".

¿Qué se libera con los punteros? ¿La información, la dirección de memoria?

Para un determinado sistema que se usa en programación de DS (las librerías EFS), uso este sistema para extraer información de la ROM para llevarla a RAM para ejecutarla, debido a este sistema cuando prescindo de ese archivo en memoria, o para cargar otro, se me hace necesario liberar los punteros utilizados para cargar otros ficheros sin tener que crear punteros nuevos cada vez. El problema es que dichos punteros son variables locales. O sea, que la variable puntero desaparece, pero la dirección de memoria queda ahí. He probado a liberarlos antes de eso, pero nada.

He de añadir que es mi primera incursión a utilizar archivos que no estuviesen previamente en la RAM, así que este tema lo tengo un poco pez.

Salu2

PD: El lenguaje que uso es C, osease que hablamos de las funciones malloc() y free().


Para recibir ayuda por parte de otros usuarios más rápidamente, recomendamos que pongas títulos descriptivos y no utilices abreviaturas (estilo MSN) en tus post de los foros. Recuerda que accediendo al Manual del perfecto forero y las Normas de la Comunidad aprenderás trucos para resolver tus dudas antes.


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de exterminator

Todo solucionado

Pues no se puede decir que haya sido fácil precisamente, pero al fin he solucionado el problema. Todos los archivos me cargan con normalidad, y no hay errores.

¿La solución? Pasé los punteros a globales, y en lugar de poner free(); y luego apuntarlo a NULL como hacía antes, simplemente apuntarlos a NULL después de usarlos, sin liberarlos. El sistema me funciona a las mil maravillas.

Muchísimas gracias a todos por ayudar.

Salu2


Para recibir ayuda por parte de otros usuarios más rápidamente, recomendamos que pongas títulos descriptivos y no utilices abreviaturas (estilo MSN) en tus post de los foros. Recuerda que accediendo al Manual del perfecto forero y las Normas de la Comunidad aprenderás trucos para resolver tus dudas antes.

Eso hará que cada vez que

Eso hará que cada vez que cargues un archivo se quede en la RAM hasta que acabe el programa... Eso no es solucionar el problema, es ocultarlo. Tarde o temprano dará error.

Imagen de exterminator

Bueno,

pues el primer problema lo he arreglado, no era de punteros, era cosa de la función (exceso de argumentos :P). Ahora el problema que tengo sí que es de punteros, de hecho viene a ser lo mismo. Libero los punteros, pero siguen apuntando al mismo archivo :S. Cargo el primer archivo, libero los punteros, y cuando cargo el segundo archivo, me vuelve a cargar el primero. De ahí deduzco que los punteros siguen con la misma dirección.

Os pongo el código, a ver si podéis ver qué pasa. Señalar que los punteros son locales. No os preocupéis por que sean EFS, es todo C y lo único raro que veréis es la carga de las librerías (EFS_Init).

/*FUNCIONES DE EFS*/
//Inicio de las EFS
void Inicializar_EFS(void)
{
	if (!EFS_Init(EFS_AND_FAT | EFS_DEFAULT_DEVICE, NULL))
	{
     PA_OutputText(1,1,1,"Error al Inicializar EFS");
     while(true) PA_WaitForVBL();
	}
}
//Obtención de punteros
u8* Obtener_Archivo (char* path) 
{ 
	FILE* file=NULL;  // Creamos una variable que sea un apuntador al fichero 
	u8* archivo=NULL;   // Creamos una variable puntero a u8  
	int  size;
	struct stat st;  //Creamos una variable stat para el fichero 
	file = fopen(path, "rb"); //Abrimos el fichero en modo lectura binaria 
	if (file != NULL) // Comprobamos que el fichero existe 
	{
		stat(path, &st);  // Volcamos los datos del fichero sobre la estructura stat
		size = st.st_size;
		archivo = (u8*)malloc(size);  // Apuntamos con el puntero al archivo
		fread(archivo, 1, size, file);  // Volcado del archivo
  		fclose(file);   // Cerramos el archivo
  		free(file);
  		free(path);
  		return (archivo);
  		free(archivo);
	} 
	else    //En caso de que no exista el fichero el programa se bloquea 
  	{ 
  		PA_OutputText (1, 0, 0, "No cogido el fichero."); 
  		PA_OutputText (0, 0, 0, "No cogido el fichero."); 
  		while (true) 
      { 
   	   PA_WaitForVBL(); 
      } 
  		return (0); 
  	}
}
//Carga de la paleta de los sprites
void LoadPal (int pantalla, int numpal, char* path) 
{ 
	u8* paleta; 
	char path_completo [EFS_MAXPATHLEN];  
	sprintf (path_completo, "%s_Pal.bin", path); // Completamos el path 
	paleta = Obtener_Archivo (path_completo); //Obtenemos el puntero 
	PA_LoadSpritePal (pantalla, numpal, paleta); // Cargamos la  paleta con el puntero
 
	free(paleta); 
}
//Carga de sprite
void LoadSprite (u8 pantalla, u8 numsprite, char* path, u8 color, u8 numpal, s16 x, s16 y) 
{ 
	u8* sprite; 
	char path_completo [EFS_MAXPATHLEN]; 
	sprintf (path_completo, "%s_Sprite.bin", path); // Completamos el path 
	sprite = Obtener_Archivo (path_completo); //Obtenemos el puntero 
	PA_CreateSprite(pantalla,numsprite,sprite,OBJ_SIZE_64X64,color,numpal,x,y);
 
	free(sprite);
}

Muchas gracias a quien me pueda ayudar.

Salu2


Para recibir ayuda por parte de otros usuarios más rápidamente, recomendamos que pongas títulos descriptivos y no utilices abreviaturas (estilo MSN) en tus post de los foros. Recuerda que accediendo al Manual del perfecto forero y las Normas de la Comunidad aprenderás trucos para resolver tus dudas antes.

Imagen de Guillermo_Cornielle

Pues

Supongo quw debes usar malloc para reservar memoria y free para liberarla, pero no entiendo exactamente que es lo que quieres hacer.

en fin, si lo que quieres el liberar la memoria, existe el valor null, o liberarla con free.


Manual del Perfecto Votante Para un voto libre y justo!.

TheGCProjects

Imagen de burnxez

Al fin

Una buena duda de programación que me ha hecho pensar un poco xD

No puedo decir que los he terminado de comprender o que mi idea de ellos es exacta y verdadera, pero al menos creo que los entiendo :-P

Primeramente, si no lo has hecho, te recomiendo leer este tutorial creado por GorristeR y a partir de ahi intentar ambos descifrar las dudas que te queden.

Saludos.

Imagen de exterminator

Ese tutorial

ya lo había revisado (antes que Google está SceneBeta xD), pero temo que la idea que da es generalizada, lo que vendría ser crear los punteros, indicarles la dirección de memoria, y usar la dirección. Sobre liberar punteros nada :(.

Por cierto, se me olvidó comentar un detalle: he liberado el puntero (supongo que la dirección de memoria), y para que no apuntase a una dirección aleatoria, lo apunté a NULL. No sé si hice bien en ponerle esto último, puesto que al finy al cabo la dirección se acaba borrando.

Se me acaba de ocurrir: ¿Y si asigno dirección NULL en el momento de declarar las variables? Llevo un rato dándole vueltas, pero no sé si arriesgarme, puesto que para comprobar si existe archivo tengo el bucle if(FILE!=NULL)...

Salu2

PD: Me alegra que mi problema te haga pensar, a mí ya me ha quemado todas las neuronas xD.


Para recibir ayuda por parte de otros usuarios más rápidamente, recomendamos que pongas títulos descriptivos y no utilices abreviaturas (estilo MSN) en tus post de los foros. Recuerda que accediendo al Manual del perfecto forero y las Normas de la Comunidad aprenderás trucos para resolver tus dudas antes.

Imagen de burnxez

Puntero = NULL

Cuando a mi me toca trabajar con punteros, lo primero que hago es crearlos apuntando a NULL. Siempre es buena idea apuntar tus punteros a NULL mientras no tengan valor.

Siempre que he trabajado con punteros lo hago de la siguiente forma:

  1. Crearlo apuntando a NULL
  2. Darle el "verdadero" valor
  3. Usarlo
  4. Apuntarlo a NULL si ya no es necesario
  5. Si lo necesito, "reutilizarlo"

Jamás he jugado con lo que dices acerca de borrar los punteros, mas que nada porque no le veo nada practico, pues yo procuro que estos sean "reutilizables" de esta manera no juego tanto con la memoria. Igual y es una mala practica, pero ha funcionado.

Ahora, si lo liberas y después lo apuntas a NULL lo estarias creando de nuevo, lo correcto seria apuntarlo a NULL y después liberarlo.

En mi caso no es necesario liberarlo pues al finalizar la aplicación también se destruyen los datos en la memoria, desconozco como maneje la NDS este aspecto.

Saludos.

Si haces free() a un puntero

Si haces free() a un puntero que apunta a NULL la lías, y mucho. El orden para punteros locales es:

 

void funcion(void)
{
void * puntero = malloc(loquesea);
 
//usar puntero
 
free(puntero);
}

 

Para punteros globales sería un pelín distinto:

void * puntero = NULL;
 
 
void funcion_crear(void)
{
if(puntero) free(puntero); //si ya hay memoria usada de antes, la liberamos
puntero = malloc(algo);
}
 
 
void funcion_usar(void)
{
if(puntero == NULL) return; //error, no hay memoria donde trabajar
 
//usar
}
 
 
void funcion_destruir(void)
{
if(puntero == NULL) return; //si no se le ha asignado nada, no hay nada que liberar
free(puntero);
puntero = NULL;
}

 

No liberar la memoria que usas, dependiendo de la situación, puede dar problemas. Por lo general, si pretendes hacer algo mínimamente complicado, te toca ir creando y liberando. Si tu programa es muy lineal y sabes que va a llegar al final sin agotar la ram, ahí si se puede pasar de liberar la memoria (yo mismo lo hago cuando programo algunas aplicaciones pequeñas para PC), pero no hay muchos casos así, y en un juego más o menos complejo vas a necesitar ir creando y destruyendo datos todo el rato.

Imagen de burnxez

Por eso dije

Que nunca habia jugado liberando punteros :-P

Para mi sonaba mas logico apuntarlo a NULL y después liberarlo, pero ahora que lo pienso bien y veo tu explicación creo que es mas logico hacerlo como dices.

Como dije, en lo que yo hago me es mas facil declarar punteros locales y usarlos, jamás los libero o algo similar y los globales simplemente los apunto a NULL, claro, esto porque es algo pequeño que se que no se tragara la RAM, aunque nunca esta de mas hacer lo que dices.

Saludos.

Imagen de Guillermo_Cornielle

Si no me equivoco

Los punteros deben declararse con el asterisco pegado al nombre de la variable, no sparado de la misma, hasta lo que yo se tu declaración daria error.


Manual del Perfecto Votante Para un voto libre y justo!.

TheGCProjects

Yo siempre los declaro así

Yo siempre los declaro así porque me parece más claro tener el asterisco separado del nombre y nunca se me ha quejado ningún compilador de los que he usado. Solo junto el asterisco cuando hago typecasts.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.