2010-03-31 5 views
11

Hasta donde yo sé, en el caso de una excepción no detectada, C++ destruye las variables locales inmediatamente, Java libera las referencias y deja el resto para el recolector de elementos no utilizados.Java y C++ en problema de desenrollado de pila

¿Es esto correcto? ¿Cuál es exactamente la diferencia entre Java y C++ en este tema? en otras palabras, ¿cuál de estos dos idiomas se considera mejor en términos de problema de desenrollado de la pila? :)

+3

Subjetivo: defina "mejor". – razlebe

+0

Java implementa un recolector de basura adecuado, por lo que, en teoría, nunca deberías preocuparte de que un objeto no destruya todo lo que crea en la pila. C++ supone que estás siendo cuidadoso. – thecoshman

+4

Java implementa un recolector de basura _memory_. Los archivos temporales no se recogen como basura, y como resultado se pueden filtrar por una pila que se desenrolla. Por otro lado, en C++ el desenrollado de la pila llama a los destructores, que además de la limpieza de la memoria también pueden limpiar los archivos temporales y otros recursos. Así que Java es más fácil y C++ más flexible, una compensación de ingeniería estándar. – MSalters

Respuesta

5

El desenrollado de pila llama específicamente a los destructores de todos los objetos completamente construidos en la cadena de llamadas hasta el punto donde se detecta la excepción.

Java simplemente no tiene ningún desenrollado de pila: no hace nada a los objetos si se produce una excepción. Debe manejar los objetos usted mismo en los bloques catch y finally. Esto es principalmente por qué C# introdujo using statements - simplifican la llamada a IDisposable.Dispose(), pero una vez más, eso no es el reemplazo completo para el desenrollado de la pila de C++.

+0

Para hacer la pregunta aquí, puede ser mejor: ¿por qué Java no tiene un mecanismo similar a un destructor que se invoca cuando el recolector de basura recoge el objeto? De esa manera, garantizamos que nuestros recursos se cierren; no importa cuándo, ya que estamos más interesados ​​en manejar las pérdidas de memoria. – Feyyaz

2

Tiene toda la razón, C++ destruye todas las variables locales, en orden inverso, ya que sale de cada función en la pila, como si estuviese ejecutando programáticamente return, y fuera de main().

9

Me voy a conseguir flameado para esto, pero ...

C++ es sin duda mejor que la de Java en la pila relajarse delante - simplemente no hay competencia. Los destructores de objetos de C++ disparan hasta la parte posterior de la pila hasta que se alcanza el punto de captura, liberando todos los recursos gestionados correctamente a lo largo del camino.

Como dijiste, Java deja todo esto a merced del recolector de basura no determinista (el peor de los casos) o en manos de los bloques finalmente creados explícitamente con los que has rellenado tu código (ya que Java no soporte verdadero RAII). Es decir, todo el código de administración de recursos está en manos de los clientes de cada clase, en lugar de estar en manos del diseñador de clases donde debería estar.

Dicho esto, en C++, el mecanismo de desenrollado de la pila solo funciona correctamente si se cuida de garantizar que los propios destructores no emitan excepciones. Una vez que tienes dos excepciones activas, tu programa abort() 's pasa sin pasar (y por supuesto sin disparar ninguno de los destructores restantes).

+0

En C++ los objetos creados en la pila reciben el llamado al destructor, pero eso no ocurre para los objetos en el montón, referenciados por un puntero en una variable local. – Mnementh

+1

@Mnementh: excepto para objetos de montón que pertenecen correctamente a un objeto con un destructor. – quamrana

+0

@quamrana: Sí, como expliqué en mi respuesta. – Mnementh

2

Para la pila haga lo mismo: liberan la pila para los bloques que deja con la excepción. En Java, todos los tipos primitivos (int, double, etc.) se guardan directamente, las variables locales de este tipo se liberan en este momento. Todos los objetos se guardan a través de referencias en variables locales, por lo que las referencias se eliminan, pero los objetos permanecen en el montón. Si esta fue la última referencia al objeto, se publican en la siguiente recolección de elementos no utilizados. Si en C++ se crean objetos en el montón y las variables locales mantienen un puntero, los objetos en el montón no se liberan automáticamente, permanecen en el montón para siempre (sí, se obtiene una FUGA DE MEMORIA). Si ha guardado objetos en la pila, se llama al destructor (y puede liberar otros objetos referenciados en el montón).

+2

Es verdad, pero los punteros inteligentes en C++ también le permiten destruir objetos asignados en el montón automáticamente. – sharptooth

+0

Correcto, los punteros inteligentes funcionan de manera diferente. – Mnementh

+2

De hecho, funcionan exactamente de la misma manera. El desenrollado de la pila llama a sus destructores y sus destructores a su vez destruyen los objetos correspondientes asignados en el montón. – sharptooth

Cuestiones relacionadas