Can a CString be an instance of IsString, Show?

There

newCString :: String -> IO CString peekCString :: CString -> IO String 

And you need

 fromString :: String -> a show :: a -> String 

My lame attempt

 {-# 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 

It seems to have worked. But, never uttering unsafePerformIO before I wonder what poverty am I creating here? Am I a memory leak? Is there a safe approach to this convenience?

+6
source share
2 answers

No. For example, your show function returns different results for the same CString at different times. This is because CString indeed a mutable string under the hood, equivalent to an IORef String . Since when the expression is evaluated and how many times the expression is evaluated, the Haskell language is not specified, the show cs expression using your instance will have a non- unsafePerformIO value, so most Haskell programmers would say that this is an invalid use from unsafePerformIO , and (intentionally) impossible to implement Show CString without using unsafePerformIO .

+8
source

This can be technically safe since you never change the memory pointed to by the CString value. Therefore, the values ​​are really immutable, and the unsafePerformIO effect simply mimics a pure value.

However, the above is only done because you never release the memory, and just leak it every time you allocate a new line using newCString .

As soon as you fix a memory leak with free , you lose security: unsafePerformIO will read everything that is on the previous memory address. If you're lucky, this will crash the program. If you're out of luck, this will read the garbage data into your lines. Good luck in debugging.

I would highly recommend against this approach.

TL DR:

  • unsafePerformIO not safe, do not use it if you do not know what you are doing.
  • C-like pointers, such as CString , should be used as little as possible and only for interaction with foreign languages.
+6
source

All Articles