[Haskell-beginners] FFI to POSIX libc; strerror (errnum); unfreed memory

Folsk Pratima folsk0pratima at cock.li
Fri Apr 12 10:39:27 UTC 2024


On Fri, 12 Apr 2024 10:59:44 +0200
Sylvain Henry <sylvain at haskus.fr> wrote:

Thank you. After getting some of my C hello worlds to have all heap
blocks freed at exit, I somehow thought that strerror can't be the
culprit.

And yes, I run valgrind on the Haskell program. No idea why so little
output, I used the -g flag. I do not really understand profiling, so I
do not know what you mean by "A valgrind profile for a Haskell program"

> Hi,
> 
> I get exactly this valgrind profile with the following C code:
> 
> #include<stdio.h>
> #include<string.h>
> 
> int main() {
>      for (int i=0; i<=450; i++) {
>          printf("%s\n", strerror(i));
>      }
> }
> 
> So there isn't anything Haskell specific here. Looking at glibc
> sources, there is a "strerror_l_buf" buffer kept in the TLS 
> (https://elixir.bootlin.com/glibc/latest/source/string/strerror_l.c#L45) 
> so that's expected.
> 
> Use strerror_r instead to use a buffer you manage explicitly (e.g.
> with allocaBytes).
> 
> Sylvain
> 
> PS: are you running valgrind on your Haskell program? A valgrind
> profile for a Haskell program has many more entries. E.g. for a
> program compiled with GHC 9.6.4:
> 
> ==36067== 2,097,152 bytes in 1 blocks are still reachable in loss
> record 21 of 21
> ==36067==    at 0x4843788: malloc (vg_replace_malloc.c:442)
> ==36067==    by 0x2AD470: stgMallocBytes (in 
> /home/hsyl20/projects/ghc/scratch/strerror/Test)
> ==36067==    by 0x2B96D8: initEventLogging (in 
> /home/hsyl20/projects/ghc/scratch/strerror/Test)
> ==36067==    by 0x2B7CFE: initTracing (in 
> /home/hsyl20/projects/ghc/scratch/strerror/Test)
> ==36067==    by 0x2A60AE: hs_init_ghc (in 
> /home/hsyl20/projects/ghc/scratch/strerror/Test)
> ==36067==    by 0x2A56F0: hs_main (in 
> /home/hsyl20/projects/ghc/scratch/strerror/Test)
> ==36067==    by 0x22D725: main (in 
> /home/hsyl20/projects/ghc/scratch/strerror/Test)
> 
> 
> On 12/04/2024 07:58, Folsk Pratima wrote:
> > I need to turn POSIX errno to the error string.
> >
> > StrError.hs
> >
> > import Foreign.C.String
> > import Foreign.C.Types
> >
> > foreign import ccall unsafe "strerror" c_strerror :: CInt -> IO
> > CString
> >
> > strError :: Int -> IO String
> > strError i = do
> >      cstr <- c_strerror ci
> >      peekCAString cstr
> >    where
> >      ci = fromIntegral i
> >
> > main = mapM_ (>>= putStrLn) $ map strError [1 .. 450]
> >
> >
> > $ ghc -g StrError.hs
> > $ valgrind --leak-check=full --show-leak-kinds=all ./StrError
> > ==2350==
> > ==2350== HEAP SUMMARY:
> > ==2350==     in use at exit: 18 bytes in 1 blocks
> > ==2350==   total heap usage: 685 allocs, 684 frees, 97,998 bytes
> > allocated ==2350==
> > ==2350== 18 bytes in 1 blocks are still reachable in loss record 1
> > of 1 ==2350==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
> > ==2350==    by 0x496A427: __vasprintf_internal (vasprintf.c:71)
> > ==2350==    by 0x493DBD5: asprintf (asprintf.c:31)
> > ==2350==    by 0x498A9F0: strerror_l (strerror_l.c:45)
> > ==2350==    by 0x408BC0: ??? (StrError.hs:8)
> > ==2350==
> > ==2350== LEAK SUMMARY:
> > ==2350==    definitely lost: 0 bytes in 0 blocks
> > ==2350==    indirectly lost: 0 bytes in 0 blocks
> > ==2350==      possibly lost: 0 bytes in 0 blocks
> > ==2350==    still reachable: 18 bytes in 1 blocks
> > ==2350==         suppressed: 0 bytes in 0 blocks
> > ==2350==
> > ==2350== For lists of detected and suppressed errors, rerun with: -s
> > ==2350== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0
> > from 0)
> >
> >
> > I am already frustrated with having to use IO for this. I feel like
> > it is better to manually create a pure solution by copying whatever
> > the C code from libc does.
> >
> > But I still do not understand what causes this memory to remain
> > reachable. Calling strerror from pure C code does not leave
> > reachable memory regions.
> >
> > Can anyone explain? And maybe you have a suggestion as to how to
> > implement this strError function properly?
> >
> > Just in case you are the type of a person to inquire as to *why* I
> > need this, for fun. I need it for fun.
> > _______________________________________________
> > Beginners mailing list
> > Beginners at haskell.org
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners  
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners



More information about the Beginners mailing list