2009-08-11 9 views
9

Tengo un programa en el que necesito salir de un gran grupo de bucles anidados. Hasta ahora, la forma en que la mayoría de la gente me ha dicho que lo haga es utilizar un goto feo en mi código.¿Utilizará goto para causar pérdidas de memoria?

Ahora, si creo un montón de pila local (creo que es lo que se llaman, si no, me refiero solo a las variables regulares sin usar el nuevo comando) las variables dentro de mis loops y mi programa da con esa declaración if que desencadena el goto, ¿encontraré una pérdida de memoria debido a que mi programa salga de muchos bucles incorrectamente y no limpie las variables locales?

+0

Usted no va a perder memoria con esos automóviles (lo que ha llamado la pila). Pero por favor NO USE GOTO. –

+8

¿Qué pasa con GOTO? –

+0

Pregunta relacionada: http://stackoverflow.com/questions/1257744 –

Respuesta

19

No, no causará una pérdida de memoria . El uso de un goto no significa "salir de bucles de forma incorrecta". Es solo generalmente no se recomienda desde un punto de vista de estructura de código.

Dejando eso de lado, cuando salga del ciclo, las variables locales saldrán del alcance y saldrán de la pila (es decir, se limpiarán) en el proceso.

+0

Ahh ahí vamos, gracias. – Faken

+0

Para salir de un bucle anticipadamente, puede: (a) usar un goto con una etiqueta. (b) utilice un objeto de condición de bucle adicional, declarado antes de los bucles y marcado en el enunciado condicional de cada bucle. (c) similar a 'b', pero verifique el estado del objeto de condición "break" si es necesario. Finalmente (d) divide la función en dos y usa un retorno para saltar fuera del ciclo. En mi humilde opinión, solo uno de estos resalta claramente la intención del autor del código. Un beneficio adicional es que goto hace que sea trivial buscar estas situaciones raras y puedan ser revisadas por pares fácilmente. –

0

No, no lo harás.

Sin embargo, asegúrese de que cualquier recurso externo se libere correctamente. Por ejemplo, si abre un archivo, sería posible pasar por alto donde normalmente estaría cerrado.

0

No. Las variables locales no necesitan ser limpiadas individualmente. Cuando la pila aparece, todas las variables locales desaparecerán junto con ella.

2

No. Solo puede filtrar la memoria asignada dinámicamente.

+1

Puede perder memoria de otras formas. Asigne unas pocas docenas de megabytes en una pila de subprocesos, luego vaya a dormir por un tiempo, por ejemplo :) – bdonlan

+2

jaja, entonces debería recibir un disparo – hobodave

+0

+1, hobodave. Usted, señor, es el primero en hacerme explotar hoy. – jkeys

1

Las variables de pila se definen (y asignan) en el momento de ingresar a la función y se eliminan implícitamente en el momento de abandonar la función (ya que todo el registro de la pila de llamadas se elimina). Ninguna cantidad de rebote dentro de la función puede causar ningún tipo de estragos con la memoria que se ha asignado todo el tiempo. Independientemente de la ruta de ejecución que tome a través del código, el registro de la pila aparecerá cuando el control vuelva a la función de llamada y la memoria se liberará.

+0

Sí, pero ¿qué sucede si no estoy usando una función? ¿Esto también es cierto si uso goto para salir de muchos bucles a la vez dentro de mi programa principal? – Faken

+0

Todo está dentro de una función, incluso si esa función es main(). El registro de pila para main() se asigna cuando se inicia el programa, y ​​se elimina cuando finaliza el programa, las mismas reglas que para cualquier otra función. – VoteyDisciple

+0

En C++ y C su código siempre se ejecuta dentro de una función u otra. Esa función puede ser main() por supuesto. –

1

Goto no siempre es malo, pero en su caso, probablemente no deba usar goto.

Vea ejemplos de buen uso de goto here y here.

Si obtiene una etiqueta que está fuera del alcance, se liberará su objeto en la pila.

Ejemplo:

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    ~A() 
    { 
    cout<<"A destructor"<<endl; 
    } 
}; 



int main(int argc, char**argv) 
{ 
    { 
    A a; 
    cout<<"Inside scope"<<endl; 
    goto l; 
    cout<<"After l goto"<<endl; 
    } 

    cout<<"Outside of scope before l label"<<endl; 

l: 
    cout<<"After l label"<<endl; 
    return 0; 
} 

Esto imprimirá:

Dentro de alcance
Un destructor
Después de l etiqueta

+0

Tiene razón, por supuesto, pero la puntualidad de la llamada de destrucción no se muestra en esta salida. ¿Tal vez agregar cout alrededor de la etiqueta 'l'? – xtofl

+0

@xtofl: Buena idea, he agregado algunos couts más para aclarar –

0

No, cualquier variable automática en sus bucles no causará fugas de programación si salta de sus bucles con una instrucción goto.

1

Las otras respuestas son ciertas ... sin embargo, si tiene que anidar bucles de manera diferente, cuestionaría el diseño que los puso allí. Dividir esa lógica en funciones separadas sería una mejor manera de resolver ese problema.

Billy3

+0

Sí, cuestiono mi lógica al usar una matriz 5D también, pero lo que funciona funciona. No sé, todo el programa comienza como un bucle gigante para empezar y simplemente sigue haciendo todo un montón de cosas en un conjunto de datos. – Faken

+0

Holy ... a ** 5D ** array? La única justificación que he tenido para eso es en PHP, donde las matrices y los objetos pueden ser lo mismo para el almacenamiento de datos ... En serio, ¿para qué necesitas una matriz 5D en C? –

+0

Por lo tanto, como un extraño darle la bienvenida. Hay más cosas en el cielo y en la tierra, Horatio, de las que sueñan en tu filosofía. –

5

variables de pila (automóviles, no autobots) no son "fugas" igual que las variables asignadas a través de nuevo() o malloc().

En cuanto a la "fealdad" de los gotos, eso es simplemente dogmático. Lee Knuth, era tan brillante como Dijkstra. http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf Evite la programación basada en pasta, pero el uso cuidadoso no se degradará en espaguetis.

A Dijkstra no le agradó porque la mayoría de lo que puede hacer con los gotos se puede hacer con otras técnicas de programación estructuradas y usa menos código, lo que hace al otro menos propenso a errores estructurados.

Comprenda que los gotos no deben ser su primera solución, y no se desvive por usarlos, pero si tiene sentido, no se someta a las moras dogmáticas lench. La declaración de break es simplemente un goto disfrazado, diseñado para casos en los que la estricta adhesión al mandamiento "No usarás gotos" no tenía sentido.

+1

A Dijkstra no le gustó porque el uso habitual de todos era una barrera para la adopción de programación estructurada. break no es "ir disfrazado" más que cualquier otra cosa o mientras "se disfrazan". Todos son constructos de programación estructurados que dan como resultado una transferencia de control no secuencial. –

+3

Break rompe la critera de "salida única" que tanto le gustaba a Dijkstra. Te deja fuera de la mitad de una construcción bien estructurada, como un bucle, que tiene una sola entrada y una única salida. Un descanso debe usarse en conjunción con una evaluación condicional para ser práctico. si goto era el tipo de declaración que dijstra quería reemplazar por una programación estructurada. si break es la construcción idéntica donde la única diferencia es goto fue reemplazado por break. La ruptura se considera solo marginalmente mejor que un goto para estos casos, ya que tiene limitaciones en cuanto a dónde se puede ir al descanso. – NoMoreZealots

+0

El descanso es considerablemente "mejor" que goto, precisamente por la razón de que solo hay un lugar donde el descanso puede ir. Tales limitaciones son exactamente lo que distingue a la programación estructurada como innovación. "Ir disfrazado" no es más que una farsa de McCarthyite: cualquiera puede encontrar cierta similitud entre absolutamente cualquier control de flujo y "goto". Pero eso no es relevante si la técnica en cuestión proporciona estructura para ayudar en la comprensión del código. La terminación de bucle con salto hace exactamente eso. –

0

Will backward goto leak resources? O cualquier otro problema potencial con el código a continuación?

reexecute:

 try 
     { 
      //Setup request 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 

      .... 

      //Get Response 
      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

      if(response != HttpStatus.OK && noOfRetries < 3) 
      { 
       noOfRetries++; 
       Thread.Sleep(10 * 1000); 


       response.Close(); 
       goto Reexecute; 
      } 
      ... 

      response.Close(); 
     } 
     catch 
     { 

     } 
Cuestiones relacionadas