`traceIO`和`hPutStrLn stderr`之间的区别是什么?

时间:2015-10-10 22:35:55

标签: debugging haskell

查看traceIO的说明,我觉得它与hPutStrLn stderr完全相同。但是,当我查看其源代码时:

traceIO :: String -> IO ()
traceIO msg = do
    withCString "%s\n" $ \cfmt -> do
     -- NB: debugBelch can't deal with null bytes, so filter them
     -- out so we don't accidentally truncate the message.  See Trac #9395
     let (nulls, msg') = partition (=='\0') msg
     withCString msg' $ \cmsg ->
      debugBelch cfmt cmsg
     when (not (null nulls)) $
       withCString "WARNING: previous trace message had null bytes" $ \cmsg ->
         debugBelch cfmt cmsg

它似乎使用了一个名为debugBelch的外部例程,我没有找到任何文档。那么traceIO可以做什么hPutStrLn stderr呢?

1 个答案:

答案 0 :(得分:4)

我能想到的一件事是它可以确保字符串作为一个单元打印,而不会在其中包含任何其他跟踪消息。事实上,一项实验似乎证实了这一点:

Prelude Debug.Trace System.IO> traceIO $ "1" ++ trace "2" "3"
2
13
Prelude Debug.Trace System.IO> hPutStrLn stderr $ "1" ++ trace "2" "3"
12
3

另一个区别是它似乎删除了无法安全打印到stderr的字符:

Prelude Debug.Trace System.IO> hPutStrLn stderr "\9731"
*** Exception: <stderr>: hPutChar: invalid argument (invalid character)
Prelude Debug.Trace System.IO> traceIO "\9731"

Prelude Debug.Trace System.IO> 

正如@dfeuer提醒我的那样,这些功能都不可能在Haskell中编写。因此决定因素可能就是:debugBelch已经是预定义的C函数,在GHC的运行时系统中使用all over the place,它是用C和C--编写的,而不是Haskell。

相关问题