1

我有一个在我的 haskell 程序中使用的外部 dll。在某些特定情况下,dll 会崩溃。

简化:首先我需要使用 MethodA 向 dll 发送一些参数,然后调用 MethodB 对这些参数进行一些计算。如果我没有提供足够的参数,那么 MethodB 将使整个 dll 崩溃。在这种情况下,我的 Haskell 应用程序也会崩溃。

有没有办法处理这个?不幸的是,dll没有抛出异常。

在 ghci 中,我收到以下消息:InitNumericalSystem::initializeSystem 中的错误。垃圾标签。

我曾尝试使用“catchAny,但这没有帮助。c_run 是我的外部 dll 方法,它需要 4 个输入参数:

catchAny :: IO a -> (SomeException -> IO a) -> IO a
catchAny = Control.Exception.catch

main :: IO ()
main = do
  let timeTot = []::[CDouble]
      timeNow = []::[CDouble]
      runType = 2::CInt
  timeTotPtr <- newArray timeTot
  timeNowPtr <- newArray timeNow
  result <- (catchAny $ c_run timeTotPtr runType timeNowPtr 0) $ \e -> do
    putStrLn $ "Got an exception: " ++ show e
    putStrLn "Returning dummy value of -1"
    return (-1)
  free timeTotPtr 
  free timeNowPtr 
  print result

编辑:我也尝试过 withAsync,但没有运气 tryAny :: IO a -> IO (Either SomeException a) tryAny action = withAsync action waitCatch

catchAny :: IO a -> (SomeException -> IO a) -> IO a
catchAny action onE = tryAny action >>= either onE return

try2 :: IO ()
try2 = do
      let timeTot = []::[CDouble]
          timeNow = []::[CDouble]
          runType = 2::CInt
      timeTotPtr <- newArray timeTot
      timeNowPtr <- newArray timeNow
      putStrLn $ "c_run going to call c_run.."
      result <- catchAny (c_run timeTotPtr runType timeNowPtr 0) (const $ return (-1))
      free timeTotPtr
      free timeNowPtr
      putStrLn $ "Result: " ++ show result
4

1 回答 1

3

如果您从 Haskell 调用 DLL 中的函数,则没有安全网可以防止 DLL 弄乱您的进程地址空间。我在这里看到三个选项:

  • 如果 DLL 有一个健全的 API,就可以在搞砸之前确定调用是否会成功。您甚至可以通过在 Haskell 的类型系统中表达这些条件来强制“正确使用”。这样,当您的 Haskell 代码编译时,DLL 也不会出现运行时崩溃。
  • DLL 提供一个函数来检查最后一次调用是否导致错误并不少见。也许你想探索这个方向。
  • 如果“崩溃”是指调用导致分段错误等,那么 Haskell / GHC / 运行时对此无能为力。您可以通过从主进程产生的单独进程调用 DLL 来隔离问题。这显然会引入生成子进程和传递数据的性能成本。
于 2013-09-23T16:32:10.057 回答