【发布时间】:2014-07-01 01:34:45
【问题描述】:
我正在尝试遵循LLVM bindings 教程here,但遇到了段错误。下面的代码工作,因为它将模块头打印到output.ll,但它也在某个地方出现了段错误。
module Main where
import Control.Monad.Error
import LLVM.General.Module
import LLVM.General.Context
import qualified LLVM.General.AST as AST
--Create and write out an empty LLVM module
main :: IO ()
main = writeModule (AST.defaultModule { AST.moduleName = "myModule" })
outputFile :: File
outputFile = File "output.ll"
writeModule :: AST.Module -> IO ()
writeModule mod = withContext $ (\context ->
liftError $ withModuleFromAST context mod (\m ->
liftError $ writeLLVMAssemblyToFile outputFile m))
--perform the action, or fail on an error
liftError :: ErrorT String IO a -> IO a
liftError = runErrorT >=> either fail return
我怀疑这与链接教程中的以下提示有关:
记住不要传递或尝试使用括号外的资源非常重要,因为这会导致未定义的行为和/或段错误。
我认为在这种情况下,“括号”是由 withContext 函数实现的,这使得看起来一切都应该处理。
如果我将writeModule 的定义更改为
writeModule mod = do assembly <- (withContext $ (\context ->
liftError $ withModuleFromAST context mod moduleLLVMAssembly))
putStrLn assembly
也就是说,我只是打印出 LLVM 程序集的字符串表示,而不是写入文件,不会引发段错误。
有人对这些绑定有经验吗?我也有兴趣了解我引用的警告的失败案例。也就是说,一个人怎么会“忘记”不使用括号外的资源?似乎需要Context 的所有功能都需要一个。这种资源范围问题不正是 Haskell 擅长为您处理的吗?
版本信息:
llvm-general-3.4.3.0LLVM version 3.4-
Default target: x86_64-apple-darwin13.2.0
【问题讨论】:
-
我猜bracket pattern 上的页面支持我对括号内容的直觉,其中指出“通常,在整个库中,定义了许多名称以
with开头的函数来管理各种以这种方式获取资源。” -
与您的问题无关:为什么您将
writeModule中的所有内容都包装在一个琐碎的do块中? -
糟糕,这可能是编辑错误。