Possible memory leak?

Chris Kuklewicz haskell at list.mightyreason.com
Tue Jul 18 10:51:12 EDT 2006


I was working on pulling library calling code from JRegex into Text.Regex.Lazy
and I am wondering if this code for compiling regex.h regular expressions is a
potential memory leak:

> regcomp pattern flags = do
>   regex_fptr <- mallocForeignPtrBytes (#const sizeof(regex_t))
>   r <- withCString pattern $ \cstr ->
>          withForeignPtr regex_fptr $ \p ->
>            c_regcomp p cstr (fromIntegral flags)
>   if (r == 0)
>      then do addForeignPtrFinalizer ptr_regfree regex_fptr
>              return (Regex regex_fptr)
>      else error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo

The (r/=0) path calls error, but never attaches the finalizer.  And the man page
for regex says:

>      The regfree() function frees any dynamically-allocated storage associated
>      with the compiled RE pointed to by preg.  The remaining regex_t is no
>      longer a valid compiled RE and the effect of supplying it to regexec() or
>      regerror() is undefined.

So it looks like the c_regcomp might allocate memory associated with regex_fptr
even in the event of an error, so this case needs the same finalizer.

I have not re-compiled GHC, but I have attached a small untested patch to change
the code to always trigger the finalizer when there is an error:

> regcomp pattern flags = do
>   regex_fptr <- mallocForeignPtrBytes (#const sizeof(regex_t))
>   addForeignPtrFinalizer ptr_regfree regex_fptr
>   r <- withCString pattern $ \cstr ->
>          withForeignPtr regex_fptr $ \p ->
>            c_regcomp p cstr (fromIntegral flags)
>   if (r == 0)
>      then return (Regex regex_fptr)
>      else do finalizeForeignPtr regex_fptr
>              error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo

Cheers,
    Chris

-------------- next part --------------
--- Text/Regex/Posix-orig.hsc	2006-07-18 11:06:55.000000000 +0100
+++ Text/Regex/Posix.hsc	2006-07-18 11:18:57.000000000 +0100
@@ -79,13 +79,14 @@
   -> IO Regex  	-- ^ Returns: the compiled regular expression
 regcomp pattern flags = do
   regex_fptr <- mallocForeignPtrBytes (#const sizeof(regex_t))
+  addForeignPtrFinalizer ptr_regfree regex_fptr
   r <- withCString pattern $ \cstr ->
     	 withForeignPtr regex_fptr $ \p ->
            c_regcomp p cstr (fromIntegral flags)
   if (r == 0)
-     then do addForeignPtrFinalizer ptr_regfree regex_fptr
-	     return (Regex regex_fptr)
-     else error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo
+     then return (Regex regex_fptr)
+     else do finalizeForeignPtr regex_fptr
+             error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo
 
 -- -----------------------------------------------------------------------------
 -- regexec



More information about the Glasgow-haskell-users mailing list