2011-05-18 7 views
44

Me preguntaba, ¿new T todavía arrojar bad_alloc si compilo mi programa usando la opción -fno-exceptions para deshabilitar el manejo de excepciones?Con "-fno-excepciones", ¿qué ocurre con "nueva T"?

¿O el compilador (GCC y clang admiten esa opción) transformará implícitamente el uso de new T en new (nothrow) T?

+1

pregunta interesante. Pero, ¿por qué quieres desactivarlo? –

+9

No quiero deshabilitarlo :) –

+0

Simplemente curioso, ¿se trata de un código que rutinariamente arroja 'bad_alloc'? –

Respuesta

25

que no puedo dar una respuesta definitiva a todas las ventajas de todo -fno-excepciones, sólo las observaciones en una máquina Linux de 32 bits, gcc 4.5.1 - bad_alloc se lanza con y sin -fno-exceptions

[21:38:35 1 ~/tmp] $ cat bad_alloc.cpp 

int main() 
{ 
    char* c = new char[4000000000U]; 
} 
[21:38:58 1 ~/tmp] $ g++ bad_alloc.cpp 
[21:39:06 1 ~/tmp] $ ./a.out 
terminate called after throwing an instance of 'std::bad_alloc' 
    what(): std::bad_alloc 
Aborted 
[21:39:07 1 ~/tmp] $ g++ -fno-exceptions bad_alloc.cpp 
[21:39:16 1 ~/tmp] $ ./a.out 
terminate called after throwing an instance of 'std::bad_alloc' 
    what(): std::bad_alloc 
Aborted 
+21

wouldn ' ¿Necesita reconstruir la biblioteca estándar de C++ con '-fno-exceptions' para obtener el resultado deseado? – rubenvb

+0

Clang detiene el código con throw desde la compilación cuando las excepciones están desactivadas, ¿tiene GCC un comportamiento similar? –

6

No es una respuesta definitiva, pero el GCC Manual (ver la sección "Hacer Sin") tiene esto:

Antes de detallar el soporte de bibliotecas para -fno-exceptions, primero una billete que pasa en las cosas perdidas cuando Se usa esta bandera : se romperán las excepciones tratando de pasar a través del código compilado con -fno-exceptions ya sea que tenga o no el código construcciones. Si tiene algún código que arroja, no debe usar -fno-exceptions.

La forma leí eso, puede que tenga que pedir explícitamente la versión de nothrow new a ser completamente seguro.

+0

que requerirá una biblioteca dinámica libstdcxx personalizada. Y dicha biblioteca no puede ser compatible con las especificaciones por los motivos que se explican aquí: http://stackoverflow.com/questions/4826838/do-standard-library-stl-containers-support-a-form-of-nothrow-allocation – Muxecoid

0

En muchos sistemas de manejo de excepciones, si la rutina "foo" llama a "bar", que a su vez llama "moo", y "moo" arroja una excepción, la única forma en que esa excepción puede volver limpiamente a "foo" es "barra" tiene código para manejar la excepción. Incluso si "barra" va a permitir que la excepción se propague sin ser detectada, generalmente deberá asegurarse de que sus variables locales se destruyan adecuadamente antes de permitir que la ejecución abandone el alcance. Esto requerirá agregar código adicional a "barra"; en la mayoría de los sistemas, parte de ese código deberá ejecutarse incluso si no se lanza ninguna excepción.

BTW, en algunos procesadores ARM como el Cortex M3, o como el Arm7 corriendo en modo ARM, si el llamador también se va a ejecutar en modo ARM, se podrían permitir excepciones sin ningún costo de tiempo de ejecución teniendo un retorno de subrutina "normal" ir a LR + 4 (cuatro bytes más allá de la dirección de retorno normal) y tener una salida excepcional ir a LR (que entonces sería una instrucción de bifurcación de 4 bytes). Sin embargo, tal comportamiento sería contrario a la práctica normal en el ARM, y tal diseño no se adaptaría muy bien al Cortex M0.

+2

Entonces, dada esa información, ¿convierte GCC 'new' a' new (nothrow) '? ;-pag –

19

Según tengo entendido, operator new está definido por libstdC++. Si ahora compila su propio código con -fno-exceptions, no puede capturar ninguna excepción, pero seguirá vinculándose con la versión normal de libstdC++, que arroja una excepción.

Así que sí, new T arrojará una excepción, incluso con -fno-exception.

Sin embargo, si compiló libstdC++ con -fno-exception también, las cosas se vuelven diferentes. Ahora, new T no puede lanzar una excepción pero, si leo the libstdc++ manual right, llamará al abort().

Parece que, si desea que su new T a devolver NULL en caso de error, la única manera es especificar explícitamente nothrow ...

Cuestiones relacionadas