[Haskell-cafe] peekCString & free memory

El Barto elbarteau at gmail.com
Sun Nov 29 14:56:51 EST 2009


Thanks for your help & time,

I checked the C API documentation:
http://xmlsoft.org/html/libxml-xmlreader.html#xmlTextReaderValue
"The result must be deallocated with xmlFree()"

I pushed the sources here:
http://github.com/gwenn/libxml-reader

My problem is with the function at line 249 in Text.XML.LibXML.XmlReader
To make it work, I have to comment out the line where xmlFree is called.

-- xmlChar * xmlTextReaderValue(xmlTextReaderPtr reader)
-- Returns:the string or NULL if not available. The result must be
deallocated with xmlFree()
foreign import ccall unsafe "xmlreader.h xmlTextReaderValue"
    c_xmlTextReaderValue :: Ptr XmlTextReader -> IO (CString)
value :: (MonadIO m) => XmlReader -> m (Maybe B.ByteString)
value (XmlReader reader_fp) = liftIO $
    withForeignPtr reader_fp $ \reader_ptr -> do
        cstr <- c_xmlTextReaderValue reader_ptr
        fromPtr B.packCString cstr c_xmlFree

fromPtr :: (Ptr a -> IO b) -> Ptr a -> (Ptr a -> IO ()) -> IO (Maybe b)
fromPtr c2h ptr free | ptr == nullPtr = return Nothing
                     | otherwise = do
                        r <- c2h ptr
                        free ptr -- FIXME
                        return (Just r)

May be the binding to xmlFree is wrong?
foreign import ccall unsafe "xmlreader.h xmlFree"
    c_xmlFree :: Ptr a -> IO ()

To test, you will need libxml2-dev:
$ runhaskell Setup configure --extra-include-dirs=/usr/include/libxml2/
$ runhaskell Setup build
$ ./dist/build/Test/Test

C functions are described here:
http://xmlsoft.org/html/libxml-xmlreader.html
And here:
http://xmlsoft.org/html/libxml-globals.html

Regards.

On Sun, Nov 29, 2009 at 7:02 PM, Duncan Coutts <duncan.coutts at googlemail.com
> wrote:

> On Sun, 2009-11-29 at 18:00 +0100, El Barto wrote:
> > Hello,
> > I get a segfault when I do
> > str <- peekCString ptr
> > free ptr
> > return (Just str)
>
> As Thomas says, you've not really given us enough info here.
>
> I'll make some guesses and observations anyway :-)
>
> > But not when I don't free the C pointer.
>
> Are you sure the C code does not also free the memory? That would lead
> to a double-free which can easily manifest as a segfault.
>
> > I also get the same behaviour with ByteString.packCString...
>
> That's pretty odd since packCString does not free the C string, it makes
> a copy. I suppose it could possibly segfault if your C string was not
> actually null terminated (as C strings must be).
>
> There are also variants that do not copy, such as
> unsafePackMallocCString. See the docs for a description.
>
> > Could you please tell me if the memory is correctly freed by GHC  when
> > I don't do it myself?
> > And how can I specify a custom free function (i.e. xmlFree function in
> > libxml2)?
>
> See the documentation for ForeignPtr.
>
> > Maybe I should use a data type with two fields : the String/ByteString
> > and the ForeignPtr to the CString?
>
> Is your C String supposed to be freed using the C free() function, or is
> it supposed to be freed using xmlFree() or something?
>
> Duncan
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20091129/be1a2018/attachment.html


More information about the Haskell-Cafe mailing list