Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Liberar memoria

Estas en el tema de Liberar memoria en el foro de C/C++ en Foros del Web. Hola, si hago muchisimas llamadas de una función recursiva con parámetros pasados por referencia, se me desborda la memoria. ¿Cómo puedo, supongamos que como yo ...
  #1 (permalink)  
Antiguo 13/01/2011, 09:20
 
Fecha de Ingreso: julio-2010
Mensajes: 216
Antigüedad: 13 años, 9 meses
Puntos: 0
Liberar memoria

Hola, si hago muchisimas llamadas de una función recursiva con parámetros pasados por referencia, se me desborda la memoria. ¿Cómo puedo, supongamos que como yo quiera, borrar toda esa información almacenada porque ya no me sirva?

Mi programa se me desborda, pero ay momentos en los cuales puedo borrar todo pues es inservible, si hago esto, no se desbordaría la memoria.

¿Sabéis cómo se borra todo?
  #2 (permalink)  
Antiguo 13/01/2011, 15:44
 
Fecha de Ingreso: enero-2008
Mensajes: 229
Antigüedad: 16 años, 3 meses
Puntos: 1
Respuesta: Liberar memoria

podrias mostrar tu código, el problema no creo que radique en los pasos por referencia, ya que un paso por referencia no realiza copias del objecto.

siempre te marca desbordamiento, tendras mal tu condicion de salida de la función recursiva?
  #3 (permalink)  
Antiguo 13/01/2011, 15:50
 
Fecha de Ingreso: junio-2006
Ubicación: España
Mensajes: 122
Antigüedad: 17 años, 11 meses
Puntos: 2
Respuesta: Liberar memoria

creo que con el fflush puedes limpiar el buffer de memoria
__________________
Twitters de famosos
  #4 (permalink)  
Antiguo 18/01/2011, 08:13
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: Liberar memoria

Cuando llamas a una función, los parámetros que le pasas los mete en la pila. Las variables locales de la función también te las crea en la pila. Ese espacio solamente se libera cuando salgas de la función. Si tienes problemas por desbordamiento de la pila (que es lo que ocurre si te pasas con la recursividad), dado que dices que los parámetros los pasas por referencia, no creo que el problema venga de ahí (tampoco sé cuál es el nivel de recursividad al que llegas, pero las referencias ocupan poca memoria).

Mira a ver qué variables tienes como locales a la función. Si, por ejemplo, tienes un array de 1000 enteros declarado de forma explícita, en cada entrada a la función te va a ocupar 4000 bytes en la pila, y eso sí puede provocarte el problema. Si, como te ha indicado Margarito04, muestras el código (al menos, la función recursiva), podría ser un poco más preciso.
  #5 (permalink)  
Antiguo 19/01/2011, 02:01
 
Fecha de Ingreso: julio-2010
Mensajes: 216
Antigüedad: 13 años, 9 meses
Puntos: 0
Respuesta: Liberar memoria

Gracias Fw190.

Entonces crees que puede ser por las variables locales que utilizo en la función.

Muestro la función recursiva. La llamada a la propia función se encuentra abajo en un FOR... num_fallos = num_fallos + ejecuta_muestra();


Aquí va el código:

__________________________________________________ _______________

Código:
int ejecuta_muestra(float* periodo_MTBF, float* MTBF, int* contadorfallosMTBF, int* primerMTBF, int primer_fallo, float* sumacuadradoMTTT, float* sumaMTTT, int transicion_pasada, float tiempos_en_umbral[num_umbrales], float hilos_indisponibilidad[1], int ultimo_hilo, int primera_ejecucion, int intentos_restantes[num_umbrales], int primer_hilo, float reloj, int umbral_hilo, int* funcionamiento_sistema, float acontecimientos[num_acontecimientos], int sistema_reparacion[tamanio_sistema_reparacion],
					 int sistema[num_elementos], float tasas_de_fallos[num_elementos], float landas[fallos_grupo], int umbrales[num_umbrales], int reintentos_umbrales[num_umbrales], int funcionamiento_sistema_[num_umbrales],
					 float reloj_[num_umbrales], float estado_float[num_umbrales][tamanio_estado_float], int estado_int[num_umbrales][tamanio_estado_int])

{
	int siguiente_acontecimiento;
        int que_elemento;
        int posicion,
        int i, 
        int posicion_umbral, 
        int fallos;
	float cantidad_a_reducir;
	int copia_sistema_reparacion[tamanio_sistema_reparacion];
        int ultimo_ha_descendido = 0;
	int num_fallos = 0;
        int hilo_fallo = 0;
        int descenso_umbral = 0;
        int total_fallos = 0;
        int vuelta_hilo;
        int fallos_antes = 0;
        int hasta_que_pos_umbral;
        float relojMTTT = 0;
	int pintar, l;


	vuelta_hilo = 0;
	if (primera_ejecucion == 0) 
	/* siempre que este subprograma se ejecuta es por nuevo hilo, y hay que volcar el  estado,
	   pero no si es la llamada inicial y es el hilo que viene de 0, ya viene inicializado desde fuera */
	{
			vuelca_estado(umbral_hilo, estado_int, estado_float, acontecimientos, sistema_reparacion, sistema, tasas_de_fallos);
            intentos_restantes[umbral_hilo-1] = intentos_restantes[umbral_hilo -1]-1; /* saber cuantos faltan para cortar ultimo al ir descendiendo */
			*funcionamiento_sistema = funcionamiento_sistema_[umbral_hilo -1]; reloj = reloj_[umbral_hilo -1];
			if (primer_hilo == 0) {/* cambiar acontecimientos para que no se repita */
					               cambia_acontecimientos(acontecimientos, tasas_de_fallos);
								  } 
	}
	
    primera_ejecucion = 0; /* no ha volcado, ya siempre puede volcar el estado */
	
	while ((vuelta_hilo == 0) && (reloj<duracion_muestra) && (descenso_umbral == 0))/* Condicion de parada de cada muestra */
	{   
		siguiente_acontecimiento=primer_acontecimiento(acontecimientos, *funcionamiento_sistema); /* vemos que acontecimiento es el siguiente */
        reloj = reloj + acontecimientos[siguiente_acontecimiento];  /* actualizamos el reloj */
        
        cantidad_a_reducir = acontecimientos[siguiente_acontecimiento]; /* almacenamos la cantidad que debemos restar a todos los acontecimientos */
		if (reloj < duracion_muestra) /* IMPORTANTE */
		{/* Cuando queda poco para llegar a los 100, puede que el proximo acontecimiento se pase y no haya que contarlo */
           
           fallos_antes = fallos_maximos(sistema);
           
           /* Movimiento */      
           if (siguiente_acontecimiento < num_servidores) /* se produce salida de un servidor */
	       {	  
                     -- No a lugar--
	       }
	       else /* se produce una llegada al sistema de reparacion */
	       {
                    -- No a lugar--
	        }
  
		    /* caluclo tiempo por encima de umbrales */
		    total_fallos = fallos_maximos(sistema);
                  
		    hasta_que_pos_umbral = hasta_que_umbral_afecta(fallos_antes, umbrales);
		    
            for (i=0;i<=hasta_que_pos_umbral;i++) 
            {
                tiempos_en_umbral[i] = tiempos_en_umbral[i] + cantidad_a_reducir;
            }
            			
		    /* *** RESTART *** */
		    total_fallos = fallos_maximos(sistema);
            
			if ((total_fallos < umbrales[umbral_hilo-1]) && !(umbral_hilo == 0))/* si se ha bajado del umbral */
			{        
					if (ultimo_hilo == 0) /* si no es ultimo hilo se corta */
					   {descenso_umbral = 1;}
					else {if ((ultimo_ha_descendido == 1) || (umbral_hilo == 1))/* es ultimo hilo y ya ha bajado o es el mas bajo*/
					         { /* si el hilo es del primer umbral no puede bajar dos veces, es excepcion */  
							     if (intentos_restantes[umbral_hilo -1] == 0) /* no quedan mas por atras */
								 {
						            umbral_hilo = umbral_hilo -1;
								    ultimo_ha_descendido = 0;
								 }
								 else{descenso_umbral = 1;} /* quedan por atras, debe cortarse */
							 }
						  else {ultimo_ha_descendido = 1; umbral_hilo = umbral_hilo -1;}
						 } 
			}
			else
			{       
					if (total_fallos == umbrales[umbral_hilo]) /* si alcanza un umbral superior */
					{
							if (umbral_hilo == (num_umbrales - 1)) /* umbral final */
							{                                                                           
                                    if (hilo_fallo == 0)
									{       
											hilo_fallo = 1;
											num_fallos++;
									}	                               						
							}
							else /* umbral intermedio */
							{		 
							        ultimo_ha_descendido = 0;
									umbral_hilo++;
								    intentos_restantes[umbral_hilo-1] = reintentos_umbrales[umbral_hilo -1]; /* se reponen */
                                    captura_estado(umbral_hilo, estado_int, estado_float, acontecimientos, sistema_reparacion, sistema, tasas_de_fallos, 
												*funcionamiento_sistema, reloj, funcionamiento_sistema_, reloj_);
								
									for (i=1;i<= reintentos_umbrales[umbral_hilo-1];i++)
									{/* el umbral 1, esta en la pos 0, etc */
											if (!(i == reintentos_umbrales[umbral_hilo-1])) {ultimo_hilo = 0;}
											else {ultimo_hilo = 1; ultimo_ha_descendido = 0;}
											
											 
											if (i==1) {primer_hilo = 1;} 
											else {primer_hilo = 0;}
											num_fallos = num_fallos + ejecuta_muestra(periodo_MTBF, MTBF, contadorfallosMTBF, primerMTBF, primer_fallo, sumacuadradoMTTT, sumaMTTT, transicion_pasada, tiempos_en_umbral, hilos_indisponibilidad, ultimo_hilo, primera_ejecucion, intentos_restantes, primer_hilo, reloj, 
											                                        umbral_hilo, funcionamiento_sistema, acontecimientos, sistema_reparacion, sistema, 
																					tasas_de_fallos, landas, umbrales, reintentos_umbrales, funcionamiento_sistema_, reloj_, estado_float, estado_int);
											vuelta_hilo = 1;
											if (no_quedan_reintentos(intentos_restantes) == 1) {return(num_fallos);}
									}
							}
					}
			}	/* fin restart */
		}
		else {/* para que salga porque ese acontecimiento ya se pasaba */
		      
			  if (*funcionamiento_sistema == 0) {hilos_indisponibilidad[0] = hilos_indisponibilidad[0]+1;
                                                 tiempos_en_umbral[num_umbrales-1] = tiempos_en_umbral[num_umbrales-1] + cantidad_a_reducir;
                                                 }
			 } 
	} /* fin de la muestra */
	
	return(num_fallos);	
}


Hay momentos en la ejecución de esta simulación que no haría falta toda la información guardada, y lo de la pila no me sirve, podría liberarla periódicamente, pero nose como. :)
Gracias por la ayuda.

Última edición por Zunri; 19/01/2011 a las 02:46
  #6 (permalink)  
Antiguo 20/01/2011, 06:39
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: Liberar memoria

En principio, por variables locales, la unica peligrosa podría ser

int copia_sistema_reparacion [tamanio_sistema_reparacion]

dependiendo, claro está, del valor tamanio_sistema_reparacion.

El problema puede proceder mas bien de la gran cantidad de parámetros que estás pasando a la funcion. La verdad es que ignoro si cuando pasas como parametro un array con su(s) dimension(es) te está pasando un puntero al primer elemento (como ocurre cuando pones solamente el nombre como puntero), o te genera una copia completa del array. Si es esto último, esa es casi seguro la fuente del problema.

Ademas convendría comprobar el nivel de recursión al que llega la función, si es muy alto podría llegar a desbordar la pila aunque en cada llamada se ocupe poco espacio. Prueba, simplemente, añadiendo un contador que se incremente y presente su valor tras cada entrada a la función, así podrás ver cuántas vueltas llevabas antes de que el programa casque (declara esa variable con el atributo static dentro de la función, algo asi como static int contador=0).

Sería conveniente (por el gran número de parámetros suministrados a la función) el agruparlos en estructuras de datos. Solamente habría que pasar un puntero por estructura, con lo que disminuye la cantidad de datos a meter en la pila cada vez, aunque en este caso podrías encontrarte con la necesidad de tener que crear y copiar la estructura completa antes de llamar a una nueva iteración, lo que puede afectar a la velocidad.

Por el momento no se me ocurre nada mas. Saludos,
  #7 (permalink)  
Antiguo 20/01/2011, 10:40
 
Fecha de Ingreso: enero-2008
Mensajes: 229
Antigüedad: 16 años, 3 meses
Puntos: 1
Respuesta: Liberar memoria

Fw190, el nombre arreglo como tal es un puntero al primer elemento del arreglo.

La sugerencia de agrupar todo en una estructura es buena idea
  #8 (permalink)  
Antiguo 21/01/2011, 01:41
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 10 meses
Puntos: 73
Respuesta: Liberar memoria

Sé que el nombre del arreglo como tal es un puntero al primer elemento. Mi duda era si al incluir las dimensiones en la llamada a la función se sigue pasando un puntero al primer elemento o se genera una copia completa del arreglo.
  #9 (permalink)  
Antiguo 21/01/2011, 10:03
 
Fecha de Ingreso: enero-2008
Mensajes: 229
Antigüedad: 16 años, 3 meses
Puntos: 1
Respuesta: Liberar memoria

no nunca, un puntero por si misma es una variable, así que lo copia es es contenido que en esta que en caso es la posición del primer elemento en el arreglo

Etiquetas: liberar, memoria
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 13:49.