有
newCString :: String -> IO CString
peekCString :: CString -> IO String
Run Code Online (Sandbox Code Playgroud)
你需要
fromString :: String -> a
show :: a -> String
Run Code Online (Sandbox Code Playgroud)
我的跛脚尝试
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverlappingInstances #-}
module Main where
import Data.String
import Foreign.C.String
import System.IO.Unsafe
instance IsString CString where
fromString = unsafePerformIO . newCString
instance {-# OVERLAPS #-} Show CString where
show = unsafePerformIO . peekCString
mycs :: CString
mycs = "hello CString"
main = putStrLn $ show mycs
Run Code Online (Sandbox Code Playgroud)
它似乎工作.但是,从来没有说过unsafePerformIO
,我想知道我在这里设置了什么样的灾难?我漏了记忆吗?有这种方便的安全方法吗?
show
不会.例如,您的功能将CString
在不同时间为相同值返回不同的结果.这是因为a CString
真的是一个可变的字符串,相当于IORef String
.因为当评估表达式并且Haskell语言没有指定表达式的计算次数时,show cs
使用您的实例的表达式将具有非确定性值,因此大多数 Haskell程序员会说这不是有效的使用unsafePerformIO
,并且它(故意)不可能在Show CString
不使用的情况下实施unsafePerformIO
.
这可能在技术上是安全的,因为您永远不会更改CString
值指向的内存.因此,这些值确实是不可变的,并且unsafePerformIO
只是模仿纯值的效果.
但是,上述情况只是因为你永远不会释放内存,而是每次分配新的字符串时都会泄漏内存newCString
.
一旦使用修复内存泄漏free
,就会失去安全性:unsafePerformIO
将读取旧内存地址中找到的内容.如果运气好的话,这会导致程序崩溃.如果你运气不好,这会将垃圾数据读入你的字符串.祝你好好调试一下.
我强烈建议不要这样做.
TL; DR:
unsafePerformIO
是不安全的,除非你知道自己在做什么,否则不要使用它. CString
应该尽可能少地使用,并且只能与外语交互. 归档时间: |
|
查看次数: |
146 次 |
最近记录: |