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!"