2017-08-08 3 views
1

プログラムが実行され、 "Divide by zero"というメッセージでクラッシュした場合、このエラーがコード内でどこで生成されたかを特定する最良の方法は何ですか?ghc 7.10.3でゼロ除算時にスタックトレースを生成する方法は?

+0

"ベスト"の資格はありますか?一般的に、スタックトレースは、怠惰な関数型言語ではあまり意味がありません。おそらく、あなたの "最良の"賭けは、プロファイリングを有効にすることです。それ以外の場合は、['CallStack'](https://hackage.haskell.org/package/base-4.10.0.0/docs/GHC-Stack.html)を使用してください。 – user2407038

+0

私は、エラーが発生したソースコード内の行を識別するメソッドを決めると思います。プロファイリングを有効にすると、いくつかの余分なパラメータ(あるもの)で 'stack build'を実行することができますか?そして、プログラムを実行すると、エラーの詳細が表示されます。 – kostmo

答えて

1

にはコールスタックがないため、GHCはスタックトレースをサポートしていません。あなたができる最善の方法は、基本モジュールGHC.Stackのシミュレーションされたスタックトレースマシンを使用することです。

GHC 7.8以降では、および7.10.3でこのように利用できる、GHC.Stackは通常のビルドにerrorのように作用するが、SCCのアノテーションを使用しています

errorWithStackTrace :: String -> a 

公開する(例えば、--fprof-autoから)おおよそのスタックトレースを構築しますプロファイルされたビルドでこれをサポートするには、プロファイリングを有効にして再コンパイルする必要があります。カバールを使用している場合は、実行することができます

cabal configure --enable-library-profiling --enable-executable-profiling 

と再構築することができます。

GHC 8.0以降、errorWithStackTraceは廃止され、コールサイト生成のサポートはHasCallStack機材によって提供されています。 GHC.Stackドキュメント、

機能から、今引用

HasCallStack制約とその呼び出しサイトを要求することができます。例えば、我々はその呼び出しサイトを取得しますerrorの変種として

errorWithCallStack :: HasCallStack => String -> a 

を定義することができます。 callStackerrorWithCallStackのコールスタックにアクセスできます。我々はerrorWithCallStackを呼び出す場合

errorWithCallStack :: HasCallStack => String -> a 
errorWithCallStack msg = error (msg ++ "n" ++ prettyCallStack callStack) 

したがって、私たちは、エラー・メッセージと一緒にフォーマットされたコールスタックを取得します。

>>> errorWithCallStack "die" 
*** Exception: die 
CallStack (from HasCallStack): 
    errorWithCallStack, called at <interactive>:2:1 in interactive:Ghci1 

(私はmsg ++ "\n"を意味して推測しているが、"n"が書かれているものです。)

あなたがGHC 7.8でいくつかの非常に限られたスタックトレースのサポートを得ることができますが、私はアップグレードをお勧めします可能であればGHC 8へのサポートが大幅に改善されました。いずれにしても、他の言語に慣れているものではありませんが、何もないよりも優れています。

+0

最新のGHCリリースでは、 'error' *は' errorWithCallStack'です。そして、ドキュメントは、あなたが 'HasCallStack'を使うよりもプロファイリングされたビルドからより良いスタックトレースを得ることを示唆しているようです。私はまだプロファイルされた方法を試していない。 – dfeuer

+0

@dfeuer GHC 8.2.1 with -' -prof'がより良いコールスタックを生成すべきであるという主張を正しく理解していますか?そうではないようです:https://gist.github。com/TomMD/7d1fb8dc762fc37bf80b7b7dd447e29a –

+0

( 'stack build --profile'を介して)プロファイリングが有効になっていても、追加のコンテキストなしで「ゼロで割ります」というエラーメッセージしか表示されません。たとえば、分割操作( '/'や '\' div \ '')が数十の呼び出しサイトに現れるコードベースがあるとしましょう。実行時に「ゼロで割る」というエラーメッセージが表示され、それらのコールサイトのどれもがエラーの原因と同じように思われる場合、デバッグにどのようにアプローチしますか? 1つの注釈付きバージョンで分割操作の各インスタンスをスワップする必要があります(せいぜい、問題のある呼び出しサイトをバイナリ検索で絞り込む必要があります)。 – kostmo