¿Escribes (realmente) código seguro de excepción? [cerrado]


El manejo de excepciones (EH) parece ser el estándar actual, y al buscar en la web, no puedo encontrar ninguna idea o método novedoso que intente mejorarlo o reemplazarlo (bueno, existen algunas variaciones, pero nada novedoso).

Aunque la mayoría de la gente parece ignorarlo o simplemente aceptarlo, EH tiene algunos inconvenientes enormes: las excepciones son invisibles para el código y crea muchos, muchos puntos de salida posibles. Joel on software escribió un artículo al respecto. La comparación con goto encaja perfecto, me hizo pensar de nuevo en EH.

Trato de evitar EH y solo uso valores de retorno, callbacks o lo que se ajuste al propósito. Pero cuando tienes que escribir código confiable, simplemente no puedes ignorar EH en estos días: Comienza con el new, que puede lanzar una excepción, en lugar de solo devolver 0 (como en los viejos tiempos). Esto hace que cualquier línea de código C++ sea vulnerable a una excepción. Y luego más lugares en las excepciones de lanzamiento de código fundacional de C++... std lib hace y así sucesivamente.

Esto se siente como caminando en terrenos inestables.. Por lo tanto, ahora estamos obligados a tener cuidado con las excepciones!

Pero es duro, es realmente duro. Usted tiene que aprender a escribir código de excepción seguro, e incluso si usted tiene alguna experiencia con él, todavía será necesario comprobar una sola línea de código para estar seguro! O empiezas a poner bloques try / catch en todas partes, lo que estorba el código hasta que alcanza un estado de no lectura.

EH reemplazó el viejo limpio enfoque determinístico (valores de retorno..), que tenía solo unos pocos pero comprensibles y fácilmente solucionables inconvenientes con un enfoque que crea muchos posibles puntos de salida en su código, y si comienza a escribir código que captura excepciones (lo que se ve obligado a hacer en algún momento), entonces incluso crea una multitud de rutas a través de su código (código en los bloques de captura, piense en un programa de servidor donde necesita instalaciones de registro que no sean std::cerr ..). EH tiene ventajas, pero eso no es el punto.

Mis preguntas reales:

  • ¿Realmente escribes código seguro de excepción?
  • ¿Está seguro de que su último código "listo para producción" es seguro para excepciones?
  • ¿Puedes estar seguro de que lo es?
  • ¿Conoce y/o realmente utiliza alternativas que funcionan?
Author: Frunsi, 2009-12-05

13 answers

Su pregunta hace una afirmación, que "Escribir código seguro para excepciones es muy difícil". Voy a responder a sus preguntas primero, y luego, responder a la pregunta oculta detrás de ellos.

Respondiendo preguntas

¿Realmente escribes código seguro de excepción?

Por supuesto que sí.

Esta es la razón por la que Java perdió mucho de su atractivo para mí como programador de C++ (falta de semántica RAII), pero estoy divagando: Esta es una pregunta de C++.

It es, de hecho, necesario cuando se necesita trabajar con código STL o Boost. Por ejemplo, los subprocesos de C++ (boost::thread o std::thread) lanzarán una excepción para salir correctamente.

¿Está seguro de que su último código "listo para producción" es seguro para excepciones?

¿Puedes estar seguro de que lo es?

Escribir código seguro para excepciones es como escribir código libre de errores.

No puede estar 100% seguro de que su código sea seguro para excepciones. Pero entonces, te esfuerzas por ello, usando patrones bien conocidos, y evitando anti-patrones bien conocidos.

¿Conoce y/o realmente utiliza alternativas que funcionan?

No hay alternativas viables en C++ (es decir, tendrá que volver a C y evitar las bibliotecas de C++, así como sorpresas externas como Windows SEH).

Escribir código seguro de excepción

Para escribir código seguro de excepción, debe saber primero qué nivel de seguridad de excepción es cada instrucción que escribe.

Para ejemplo, un new puede lanzar una excepción, pero asignar un built-in (por ejemplo, un int, o un puntero) no fallará. Un intercambio nunca fallará (nunca escriba un intercambio de lanzamiento), un std::list::push_back puede lanzar...

Garantía de excepción

Lo primero que debe entender es que debe ser capaz de evaluar la garantía de excepción ofrecida por todas sus funciones:

  1. none: Tu código nunca debería ofrecer eso. Este código filtrará todo y se descompondrá al principio excepción lanzada.
  2. basic : Esta es la garantía que debe ofrecer como mínimo, es decir, si se lanza una excepción, no se filtran recursos, y todos los objetos siguen siendo completos
  3. strong: El procesamiento tendrá éxito o lanzará una excepción, pero si lanza, entonces los datos estarán en el mismo estado que si el procesamiento no se hubiera iniciado en absoluto (esto le da una potencia transaccional a C++)
  4. nothrow / nofail : El procesamiento éxito.

Ejemplo de código

El siguiente código parece C++ correcto, pero en verdad, ofrece la garantía de "ninguno", y por lo tanto, no es correcto:

void doSomething(T & t)
{
   if(std::numeric_limits<int>::max() > t.integer)  // 1.   nothrow/nofail
      t.integer += 1 ;                              // 1'.  nothrow/nofail
   X * x = new X() ;                // 2. basic : can throw with new and X constructor
   t.list.push_back(x) ;            // 3. strong : can throw
   x->doSomethingThatCanThrow() ;   // 4. basic : can throw
}

Escribo todo mi código con este tipo de análisis en mente.

La garantía más baja ofrecida es básica, pero entonces, el orden de cada instrucción hace que toda la función sea "ninguna", porque si 3. lanza, x se filtrará.

Lo primero a hacer sería hacer la función "básica", es decir poner x en un puntero inteligente hasta que sea propiedad segura de la lista:

void doSomething(T & t)
{
   if(std::numeric_limits<int>::max() > t.integer)  // 1.   nothrow/nofail
      t.integer += 1 ;                              // 1'.  nothrow/nofail
   std::auto_ptr<X> x(new X()) ;    // 2.  basic : can throw with new and X constructor
   X * px = x.get() ;               // 2'. nothrow/nofail
   t.list.push_back(px) ;           // 3.  strong : can throw
   x.release() ;                    // 3'. nothrow/nofail
   px->doSomethingThatCanThrow() ;  // 4.  basic : can throw
}

Ahora, nuestro código ofrece una garantía "básica". Nada se filtrará, y todos los objetos estarán en un estado correcto. Pero podríamos ofrecer más, es decir, la fuerte garantía. Aquí es donde puedevolverse costoso, y esta es la razón por la que no todo el código de C++ es fuerte. Vamos a intentarlo:

void doSomething(T & t)
{
   // we create "x"
   std::auto_ptr<X> x(new X()) ;    // 1. basic : can throw with new and X constructor
   X * px = x.get() ;               // 2. nothrow/nofail
   px->doSomethingThatCanThrow() ;  // 3. basic : can throw

   // we copy the original container to avoid changing it
   T t2(t) ;                        // 4. strong : can throw with T copy-constructor

   // we put "x" in the copied container
   t2.list.push_back(px) ;          // 5. strong : can throw
   x.release() ;                    // 6. nothrow/nofail
   if(std::numeric_limits<int>::max() > t2.integer)  // 7.   nothrow/nofail
      t2.integer += 1 ;                              // 7'.  nothrow/nofail

   // we swap both containers
   t.swap(t2) ;                     // 8. nothrow/nofail
}

Reordenamos las operaciones, primero creando y ajustando X a su valor correcto. Si alguna operación falla, entonces t no se modifica, por lo que la operación 1 a 3 puede considerarse "fuerte": Si algo se lanza, t no se modifica, y X no se filtrará porque es propiedad del puntero inteligente.

Luego, creamos una copia t2 de t, y trabajamos en esta copia desde la operación 4 a la 7. Si algo se lanza, t2 se modifica, pero entonces, t sigue siendo el original. Todavía ofrecemos la garantía fuerte.

Luego, intercambiamos t y t2. Las operaciones de swap deberían ser nothrow en C++, así que esperemos el intercambio para el que escribiste T es nothrow (si no lo es, reescríbelo para que sea nothrow).

Entonces, si llegamos al final de la función, todo tuvo éxito (Sin necesidad de un tipo de retorno) y t tiene su valor exceptuado. Si falla, entonces t tiene todavía su valor original.

Ahora, ofrecer la garantía fuerte podría ser bastante costoso, así que no se esfuerce por ofrecer la garantía fuerte a todo su código, pero si puede hacerlo sin un costo (y C++ inlining y otra optimización podría hacer todo el código anterior sin costo), a continuación, hacerlo. El usuario de la función te lo agradecerá.

Conclusión

Se necesita algún hábito para escribir código seguro de excepciones. Tendrá que evaluar la garantía ofrecida por cada instrucción que utilizará, y luego, tendrá que evaluar la garantía ofrecida por una lista de instrucciones.

Por supuesto, el compilador de C++ no respaldará la garantía (en mi código, ofrezco la garantía como una etiqueta @ warning doxygen), lo cual es un poco triste, pero debería no le impide intentar escribir código seguro de excepciones.

Fallo normal vs. error

¿Cómo puede un programador garantizar que una función no-fail siempre tendrá éxito? Después de todo, la función podría tener un error.

Esto es cierto. Se supone que las garantías de excepción son ofrecidas por código libre de errores. Pero entonces, en cualquier idioma, llamar a una función supone que la función está libre de errores. Ningún código cuerdo se protege contra la posibilidad de que tenga un error. Escribe el código mejor que tú puede, y luego, ofrecer la garantía con la suposición de que está libre de errores. Y si hay un error, corríjalo.

Las excepciones son para errores de procesamiento excepcionales, no para errores de código.

Últimas palabras

Ahora, la pregunta es "¿Vale la pena?".

Por supuesto, lo es. Tener una función "nothrow / no-fail" saber que la función no fallará es una gran bendición. Lo mismo puede decirse de una función "fuerte", que le permite escribir código con semántica transaccional, al igual que las bases de datos, con características de commit/rollback, el commit es la ejecución normal del código, lanzando excepciones es el rollback.

Entonces, lo "básico" es la garantía mínima que debe ofrecer. C++ es un lenguaje muy fuerte allí, con sus alcances, lo que le permite evitar cualquier fuga de recursos (algo que un recolector de basura encontraría difícil ofrecer para la base de datos, la conexión o los manejadores de archivos).

Así que, hasta donde yo lo veo, vale se.

Editar 2010-01-29: Sobre el intercambio no lanzador

Nobar hizo un comentario que creo, es bastante relevante, porque es parte de"cómo escribir código seguro de excepción":

  • [me] Un intercambio nunca fallará (ni siquiera escriba un intercambio de lanzamiento)
  • [nobar] Esta es una buena recomendación para funciones personalizadas swap(). Cabe señalar, sin embargo, que std::swap() puede fallar en función de las operaciones que utiliza internamente

El valor predeterminado std::swap hará copias y asignaciones, que, para algunos objetos, puede lanzar. Por lo tanto, el swap predeterminado podría lanzar, ya sea utilizado para sus clases o incluso para las clases STL. En lo que respecta al estándar C++, la operación de intercambio para vector, deque, y list no lanzará, mientras que podría para map si el funtor de comparación puede lanzar en la construcción de copia (Véase El Lenguaje de programación C++, Edición Especial, apéndice E, E. 4.3.Swap ).

Mirando la implementación de Visual C++ 2008 de el intercambio del vector, el intercambio del vector no lanzará si los dos vectores tienen el mismo asignador (es decir, el caso normal), pero hará copias si tienen diferentes asignadores. Y por lo tanto, supongo que podría tirar en este último caso.

Por lo tanto, el texto original todavía se mantiene: No escriba nunca un intercambio de lanzamiento, pero debe recordarse el comentario de nobar: Asegúrese de que los objetos que está intercambiando tengan un intercambio de no lanzamiento.

Editar 2011-11-06: Interesante artículo

Dave Abrahams, quien nos dio las garantías basic/strong/nothrow, describió en un artículo su experiencia sobre hacer segura la excepción STL:

Http://www.boost.org/community/exception_safety.html

Mire el punto 7 (Pruebas automatizadas para la excepción-seguridad), donde se basa en pruebas unitarias automatizadas para asegurarse de que cada caso sea probado. Supongo que esta parte es una excelente respuesta a la pregunta del autor " ¿Puede incluso estar seguro de que es?".

Editar 31-05-2013: Comentario de dionadar

t.integer += 1; es sin la garantía de que el desbordamiento no va a suceder NO excepción seguro, y de hecho puede invocar técnicamente UB! (Signed overflow is UB: C++11 5/4 "Si durante la evaluación de una expresión, el resultado no está definido matemáticamente o no está en el rango de valores representables para su tipo, el comportamiento es indefinido.") Tenga en cuenta que los enteros sin signo no se desbordan, pero hacer sus cálculos en una clase de equivalencia módulo 2^ # bits.

Dionadar se refiere a la siguiente línea, que de hecho tiene un comportamiento indefinido.

   t.integer += 1 ;                 // 1. nothrow/nofail

La solución aquí es verificar si el entero ya está en su valor máximo (usando std::numeric_limits<T>::max()) antes de hacer la adición.

Mi error iría en la sección "Fallo normal vs.bug", es decir, un bug. No invalida el razonamiento, y no significa que el código exception-safe sea inútil porque sea imposible de alcanzar. Usted no puede protegerse contra el apagado de la computadora, o errores del compilador, o incluso sus errores u otros errores. No puedes alcanzar la perfección, pero puedes tratar de acercarte lo más posible.

Corregí el código con el comentario de Dionadar en mente.

 496
Author: paercebal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-03 06:30:31

Escribir código a prueba de excepciones en C++ no se trata tanto de usar muchos bloques try { } catch {}. Se trata de documentar qué tipo de garantías ofrece su código.

Recomiendo leer la serie de Herb Sutter Guru Of The Week , en particular las entregas 59, 60 y 61.

Para resumir, hay tres niveles de seguridad de excepción que puede proporcionar:

  • Básico: Cuando su código lanza una excepción, su código no filtra recursos y los objetos permanecen destructible.
  • Strong: Cuando su código lanza una excepción, deja el estado de la aplicación sin cambios.
  • No lanzar: Su código nunca lanza excepciones.

Personalmente, descubrí estos artículos bastante tarde, por lo que gran parte de mi código C++ definitivamente no es seguro para excepciones.

 30
Author: Joh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 20:37:14

Algunos de nosotros hemos estado usando la excepción por más de 20 años. PL / I los tiene, por ejemplo. La premisa de que son una tecnología nueva y peligrosa me parece cuestionable.

 17
Author: bmargulies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 20:03:25

En primer lugar (como dijo Neil), SEH es el Manejo Estructurado de Excepciones de Microsoft. Es similar pero no idéntico al procesamiento de excepciones en C++. De hecho, usted tiene que permitir excepciones de C++ si lo quieres en Visual Studio - el comportamiento predeterminado no garantiza que los objetos son destruidos en todos los casos! En cualquier caso, el Manejo de excepciones no es realmente más difíciles simplemente diferente.

Ahora para su actual pregunta.

¿Realmente escribes código seguro de excepción?

Sí. Me esfuerzo por un código seguro de excepción en todos los casos. Evangelizo usando las técnicas RAII para el acceso a los recursos (e. g., boost::shared_ptr para la memoria, boost::lock_guard para bloquear). En general, el uso consistente de las técnicas RAII y scope guarding hará que el código seguro de excepciones sea mucho más fácil de escribir. El truco es aprender lo que existe y cómo aplicarlo.

¿Está seguro de que su último código "listo para producción" es seguro para excepciones?

No. Es tan seguro como lo es. Puedo decir que no he visto un fallo en el proceso debido a una excepción en varios años de actividad 24/7. No espero un código perfecto, sólo un código bien escrito. Además de proporcionar seguridad de excepción, las técnicas anteriores garantizan la corrección de una manera que es casi imposible de lograr con try/catch bloques. Si usted está cogiendo todo en su alcance de control superior (hilo, proceso, etc.), entonces puede estar seguro de que continuará corriendo frente a las excepciones ( la mayor parte del tiempo). Las mismas técnicas también le ayudarán a continuar ejecutando correctamente ante las excepciones sin try/catch bloques en todas partes.

¿Puedes estar seguro de que lo es?

Sí. Usted puede estar seguro por una auditoría de código a fondo, pero nadie realmente hace que hacen? Revisiones regulares de código y desarrolladores cuidadosos van a aunque hay un largo camino para llegar allí.

¿Conoce y/o realmente utiliza alternativas que funcionan?

He probado algunas variaciones a lo largo de los años, como estados de codificación en los bits superiores (ala HRESULTs ) o que horrible setjmp() ... longjmp() hack. Ambos se descomponen en la práctica, aunque de maneras completamente diferentes.


Al final, si usted consigue en el hábito de aplicar algunas técnicas y pensar cuidadosamente sobre dónde puede realmente haga algo en respuesta a una excepción, terminará con un código muy legible que es seguro de excepción. Puede resumir esto siguiendo estas reglas:

  • Solo quieres ver try/catch cuando se puede hacer algo acerca de una excepción específica
  • Casi nunca quieres ver un raw new o delete en código
  • Evitar std::sprintf, snprintf, y arrays en general-use std::ostringstream para formatear y reemplazar arrays con std::vector y std::string
  • en caso de duda, busque funcionalidad en Boost o STL antes de rodar su propio

Solo puedo recomendar que aprenda a usar las excepciones correctamente y se olvide de los códigos de resultados si planea escribir en C++. Si desea evitar excepciones, es posible que desee considerar escribir en otro idioma que no las tenga o las haga seguras. Si realmente quieres aprender a utilizar completamente C++, lee algunos libros de Herb Sutter, Nicolai Josuttis , y Scott Meyers .

 16
Author: D.Shawley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 21:00:37

No es posible escribir código a prueba de excepciones bajo el supuesto de que "cualquier línea puede lanzar". El diseño del código seguro para excepciones se basa fundamentalmente en ciertos contratos / garantías que se supone que debe esperar, observar, seguir e implementar en su código. Es absolutamente necesario tener código que esté garantizado para nunca lanzar. Hay otros tipos de garantías de excepción por ahí.

En otras palabras, crear código seguro de excepciones es en gran medida una cuestión de program designno es solo una cuestión de codificación simple .

 9
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 21:09:32
  • ¿Realmente escribes código seguro de excepción?

Bueno, ciertamente pretendo hacerlo.

  • ¿Está seguro de que su último código "listo para producción" es seguro para excepciones?

Estoy seguro de que mis servidores 24/7 construidos usando excepciones se ejecutan 24/7 y no pierden memoria.

  • ¿Puedes estar seguro de que lo es?

Es muy difícil estar seguro de que cualquier código es correcto. Por lo general, uno solo puede ir por resultados

  • ¿Conoce y / o utiliza realmente ¿alternativas que funcionan?

No. Usar excepciones es más limpio y fácil que cualquiera de las alternativas que he usado en los últimos 30 años en programación.

 7
Author: anon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 20:09:47

Dejando de lado la confusión entre las excepciones SEH y C++, debe ser consciente de que las excepciones se pueden lanzar en cualquier momento, y escribir su código con eso en mente. La necesidad de seguridad de excepción es en gran medida lo que impulsa el uso de RAII, punteros inteligentes y otras técnicas modernas de C++.

Si sigue los patrones bien establecidos, escribir código seguro de excepciones no es particularmente difícil, y de hecho es más fácil que escribir código que maneja correctamente los retornos de errores en todos los casos.

 5
Author: Mark Bessey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 20:10:42

EH es bueno, generalmente. Pero la implementación de C++no es muy amigable, ya que es realmente difícil decir qué tan buena es la cobertura de captura de excepciones. Java por ejemplo hace esto fácil, el compilador tenderá a fallar si no maneja posibles excepciones .

 4
Author: Mr. Boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-29 10:59:16

Sin embargo, me gusta mucho trabajar con Eclipse y Java (nuevo en Java), porque arroja errores en el editor si le falta un controlador EH. Eso hace que las cosas sean mucho más difíciles de olvidar para manejar una excepción...

Además, con las herramientas IDE, agrega automáticamente el bloque try / catch u otro bloque catch.

 2
Author: Crowe T. Robot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 20:11:10

Algunos de nosotros preferimos lenguajes como Java que nos obligan a declarar todas las excepciones lanzadas por los métodos, en lugar de hacerlas invisibles como en C++ y C#.

Cuando se hace correctamente, las excepciones son superiores a los códigos de retorno de error, si por ninguna otra razón que no tiene que propagar los fallos a la cadena de llamadas manualmente.

Dicho esto, la programación de bibliotecas de API de bajo nivel probablemente debería evitar el manejo de excepciones y atenerse a los códigos de retorno de errores.

Ha sido mi experimente que es difícil escribir código limpio para el manejo de excepciones en C++. Termino usando new(nothrow) mucho.

 2
Author: David R Tribble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-05 20:12:19

Hago todo lo posible para escribir código seguro de excepciones, sí.

Eso significa que tengo cuidado de mantener un ojo en que líneas pueden lanzar. No todo el mundo puede, y es de vital importancia tenerlo en cuenta. La clave es realmente pensar en, y diseñar su código para satisfacer, las garantías de excepción definidas en el estándar.

¿Se puede escribir esta operación para proporcionar la fuerte garantía de excepción? ¿Tengo que conformarme con el básico? Qué líneas pueden lanzar excepciones, y ¿cómo puedo asegurarme de que si lo hacen, no corrompen el objeto?

 2
Author: jalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-06 10:52:51
  • ¿Realmente escribes código seguro de excepción? [No existe tal cosa. Las excepciones son un escudo de papel a los errores a menos que tenga un entorno administrado. Esto se aplica a las tres primeras preguntas.]

  • ¿Conoces y / o utilizas alternativas que funcionen? [Alternativa a qué? El problema aquí es que la gente no separa los errores reales del funcionamiento normal del programa. Si es el funcionamiento normal del programa (es decir, un archivo no encontrado), no es realmente el manejo de errores. Si es un verdadero error, no hay manera de 'manejarlo' o no es un error real. Su objetivo aquí es averiguar qué salió mal y detener la hoja de cálculo y registrar un error, reiniciar el controlador de su tostadora, o simplemente rezar para que el jetfighter pueda continuar volando incluso cuando su software tiene errores y esperar lo mejor.]

 2
Author: Charles Eli Cheese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-07 02:27:21

Mucha (incluso diría que la mayoría) gente lo hace.

Lo que es realmente importante acerca de las excepciones, es que si no escribes ningún código de manejo, el resultado es perfectamente seguro y bien comportado. Demasiado ansioso por entrar en pánico, pero seguro.

Necesita activamente cometer errores en los controladores para obtener algo inseguro, y solo atrapar(...) {} se comparará con ignorar el código de error.

 0
Author: ima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-06 18:53:24