Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





throw en C++

Iniciado por swapd0, 14 de Abril de 2008, 01:09:37 AM

« anterior - próximo »

swapd0

Hola, echando un vistazo a una clase sobre smart pointers me encuentro con el siguiente codigo

...
   T * get() throw() { return mPtr; }
...


¿Alquien sabe para que se pone ahi el throw? Tambien aparece en otras funciones miembro y en los constructores, pero lo que me mosquea es que no esta en la parte del codigo.

Prompt

Link



Towards the end of the comments in my last "What's wrong with this code" , hippietim asked why I added a throw()attribute to the destructor of the CCoInitializer.  The answer's pretty simple.  If you add a throw() attribute around routines that never throw, the compiler can be clever about code motion and optimization.  Consider the following totally trivial:

class MyClass
{
   size_t CalculateFoo()
   {
       :
       :
   };
   size_t MethodThatCannotThrow() throw()
   {
       return 100;
   };
   void ExampleMethod()
   {
       size_t foo, bar;
       try
       {
           foo = CalculateFoo();
           bar = foo * 100;
           MethodThatCannotThrow();
           printf("bar is %d", bar);
       }
       catch (...)
       {
       }
   }
};




When the compiler sees this, with the "throw()" attribute, the compiler can completely optimize the "bar" variable away, because it knows that there is no way for an exception to be thrown from MethodThatCannotThrow().  Without the throw() attribute, the compiler has to create the "bar" variable, because if MethodThatCannotThrow throws an exception, the exception handler may/will depend on the value of the bar variable.

In addition, source code analysis tools like prefast can (and will) use the throw() annotation to improve their error detection capabilities - for example, if you have a try/catch and all the functions you call are marked as throw(), you don't need the try/catch (yes, this has a problem if you later call a function that could throw).

Nifty Win32 tricks

Prompt

Si pones throw() en la función no será posible generar una excepción. Como bien dice, eso provoca que el compilador pueda optimizar todas las variables, entre ellas pone el ejemplo de "Bar".

Ahora bien, 2 consideraciones, no vale de nada que llames a esos métodos dentro de un try / catch y que dios sabe si podras saber donde ha petado el código limpiamente.

Quizás compilando con todas las optimizaciones activadas la perdida de rendimiento no sea tanta, todo es cuestion de probar y hacer profile. Claro está asegurandote de que la parte de código que vas a dejar con esos throw sea muy estable.

Un saludete!

Zaelsius

C++ es como tu mujer/novia, nunca la terminas de conocer del todo :D

Digo yo que ya podían haberlo llamado "nothrow()"

davur

La creencia de que las especificaciones de excepciones permiten optimizaciones del compilador en base al conocimiento (estático) de que una determinada función sólo lanzará excepciones de tipos determinados (o ninguna en absoluto) es errónea. De hecho, ante una especificación de excepciones, el compilador inyecta bloques try/catch implícitos envolviendo el cuerpo de la función para asegurar (dinámicamente) que la función realmente sólo emite excepciones del tipo especificado (excepto en aquellos casos en que tenga conocimiento estático de ello).

La realidad es que utilizar la especificación throw() en una función no-inline puede tener _algunos_ beneficios en _algunos_ compiladores. Y decir esto es decir mucho (o muy poco), especialmente en un contexto de desarrollo multiplataforma.

Tomando el mismo fragmento de código de swapd0:

T * get() throw() { return mPtr; }

Un buen compilador puede deducir que esta función, declarada inline, es incapaz de generar una excepción, y aplicar el mismo tipo de optimizaciones que uno podría esperar al utilizar la especificación throw(). Sin embargo, un mal compilador puede desactivar el inlining al encontrarse con una especificación de excepciones, o generar bloques try/catch igualmente; afectando negativamente al rendimiento de la función.

Moraleja: en general, no escribas nunca especificaciones de excepciones.

ethernet

Dejando a un lado si el compilador optimiza y mirando los lenguajes medallistas en el lanzamiento de excepciones (lease java), al final terminas con código lleno de :


try {...} catch(Exception){}


que hace exactamente lo mismo que nada. Será que soy muy tradicional, pero me sigue gustando retornar true o false :)

Vicente

Cita de: "ethernet"Dejando a un lado si el compilador optimiza y mirando los lenguajes medallistas en el lanzamiento de excepciones (lease java), al final terminas con código lleno de :


try {...} catch(Exception){}


que hace exactamente lo mismo que nada. Será que soy muy tradicional, pero me sigue gustando retornar true o false :)

<Off-Topic>
En la guía de diseño de librerías de clases de Microsoft te encuentras esta frase ;)

Citar
Do not overuse catch. Exceptions should often be allowed to propagate up the call stack.

Catching exceptions that you cannot legitimately handle hides critical debugging information.

Este es el capítulo sobre excepciones:

http://msdn2.microsoft.com/en-us/library/ms229014.aspx
</Off-Topic>

Un saludo! :p

Vicente






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.