Hi!

Consider the following program:
\begin{code}
{-# OPTIONS -fglasgow-exts #-}
import Addr
import CString
import Monad (when)

foreign import ccall "free" unsafe free :: Addr -> IO ()

main = do
    (addr::Addr) <- _casm_ ``%r = strdup ("This is esoteric.");''
    if addr /= nullAddr 
      then do
        str <- unpackCStringIO addr
        free addr
        putStrLn $ "Got `" ++ str ++ "'" -- (**)
      else putStrLn "(null)"
    putStrLn "Done"
\end{code}

with ghc-4.04-19990916 you get The Right Thing(TM):
----
Got `This is esoteric.'
Done
----

Unfortunately, with ghc-4.05-19991206 you get:
----
Done
----
which is wrong in any case!

IMHO, `str' isn't fully evaluated before `free addr' frees its memory.
Specifically, only the first char seems to get evaluated...

A slightly modified version, like:
         str <- unpackCStringIO addr
+        putStrLn "FOO" 
         free addr

yields:
----
FOO
Got `TL@ĝL@esoteric.'
Done
----

The garbage gets into the strdup'd copy of the string _after_ the call to
`free', and from there it is copied for the (**) closure, AFAICT.


BTW, if I s/unpackCStringIO/unmarshallString/g :
\begin{code}
unmarshallString :: Addr -> IO String
unmarshallString adr = us 0
  where
    us ofs = do
      ch <- readCharOffAddr adr ofs
      if ch /= '\NUL'
        then liftM (ch:) $ us (ofs + 1)
        else return []
\end{code}
and leave `putStrLn "FOO"' in place(!), then I get:
----
FOO
Got `This is esoteric.'
Done
----


Can somebody please have a look at this?

BTW: The GHC Team isn't holding shares from "Bayer Chemicals" (Aspirin(TM)
inventor), is it? }}|->


Cheers,
Michael
-- 
* Software Engineering is like looking for a black cat in a dark room in
  which there is no cat.
* Systems Engineering is like looking for a black cat in a dark room in
  which there is no cat and someone yells "I got it!"

Reply via email to