2011-12-21 7 views
11

Estoy buscando algo para reemplazar loch (y su preprocesador) ya que no se compila con GHC 7.¿Cómo puedo obtener la posición donde se invocó el error?

En concreto, si error se llama entonces me gustaría averiguar, tan convenientemente como sea posible, donde fue llamado desde (el número de línea y el seguimiento de la pila sería bueno).

+0

Realmente no se puede controlar dónde o cuando otras bibliotecas utilizan 'error', pero mi preferencia personal por mi propio código es evitar 'error' tanto como sea posible. Como consejo general para cualquiera que lea esto, si necesita saber por qué el código está tomando una rama de ejecución particular, * no * use 'error' para encontrar un seguimiento de pila; la mejor manera en este momento es probablemente 'Debug.Trace'. –

+0

@ DanBurton No creo que esto se aplique a lo que estoy pidiendo. Digamos que ejecuto mi programa y de forma inesperada obtengo '*** Exception: Prelude.head: empty list', ahora me gustaría saber dónde está la llamada a la cabeza que produjo este error en el código fuente. – HaskellElephant

+0

Tengo un parche para ghc que agrega eso. Necesito fusionarlo. – augustss

Respuesta

12

Puede usar la opción -xc RTS, como se describe en this page; necesita compilar su programa con soporte de perfiles, y la salida es bastante fea, pero funciona.

Esto debe hacerlo:

$ ghc --make -prof -auto-all myprog.hs 
$ ./myprog +RTS -xc 

Técnicamente esto sólo da un centro de pila costo, no es un verdadero seguimiento de la pila. El soporte de seguimiento de pila mejorado es coming in GHC 7.4.

5

Si esto es para usar en el código en el que está trabajando, y puede tolerar el uso de Template Haskell, the placeholders package es una forma linda y sencilla de hacer algo como esto. Sin embargo, no le ayudará a encontrar la ubicación de las expresiones reales error, solo utiliza sus propias funciones similares a error.

5

Es bastante trivial conseguirlo para construir con GHC-7. Es solo el cambio Control.Exception que vino con 6.12, la solución simple es cambiar el tipo Exception a SomeException en Debug.Trace.Location, línea 70 y agregar una firma de tipo de expresión en la línea 144. Restringir la dependencia base a >= 4.2 && < 4.6 en el archivo .cabal (topar el versión) y estás listo para ir.

3

Una solución rápida y sucia es la función assert de Control.Exception. Sin embargo, es un poco más ruidoso que error.

Advertencia: Todo afirma serán ignoradas en silencio si se compila con optimizaciones (ghc -O1, -O2, etc.).

Ejemplo:

import Control.Exception 

main = do 
    print (42 + (assert True 17)) -- adds 42 and 17 
    print (42 + (assert False 21)) -- crashes 

de salida:

59 
test.hs: /tmp/test.hs:5:18-23: Assertion failed 

Nota el número de línea "5" en la salida.

Usted podría utilizar trace de Debug.Trace para agregar un mensaje de error:

print (42 + (trace "omg error" $ assert False 21)) 
Cuestiones relacionadas