gr_stream design

53 views
Skip to first unread message

Hartmut Monien

unread,
Jul 29, 2024, 8:52:39 AM7/29/24
to flint-devel
I encountered serious problems when wrapping IO for gr. The memory of the gr type is corrupted after output. 

So what I see is that FLINT_FILE is open in gr_stream_init_file and a string is allocated in gr_stream_init_str. 

- where is the file handle ever closed?
- is the user supposed to deallocate the string of gr_stream and if so where?
- the string is freed after writing an fmpz but not after writing a ui or si?

Fredrik Johansson

unread,
Jul 29, 2024, 9:32:14 AM7/29/24
to flint...@googlegroups.com
Hello Hartmut,

gr_stream_init_file takes an existing file pointer as input. Currently there is no method to retrieve the file pointer from the stream object, so you will either have to reach into the gr_stream_struct yourself or store a copy of the file pointer externally until you've finished writing to the stream. So the usage should be something like this:

FILE * fp = fopen(...);
gr_stream_init_file(stream, fp);
gr_write(stream, x, ctx);
gr_write(stream, y, ctx);
gr_write(stream, z, ctx);
fclose(fp);
/* At this point, stream can no longer be used */

For a stream created with gr_stream_init_str, the string is allocated internally and may be resized internally. You can retrieve the current pointer with gr_get_str. Once you have done so, you should not do any further writes to the same stream object since this could invalidate the pointer. Retrieving and freeing the string is basically how you clear such a stream object.

gr_stream_init_str(stream);
gr_write(stream, x, ctx);
gr_write(stream, y, ctx);
gr_write(stream, z, ctx);
s = gr_get_str(stream);
flint_printf("%s\n", s);
flint_free(s);
/* At this point, stream can no longer be used */


> - the string is freed after writing an fmpz but not after writing a ui or si?

gr_stream_write_si, gr_stream_write_ui and gr_stream_write_fmpz don't write directly to the stream; they write to a temporary string and then copy that string into the stream. For gr_stream_write_fmpz this temporary string is malloced and thus needs to be freed. This is an implementation detail which you normally shouldn't need to be concerned with externally.

Fredrik

--

---
You received this message because you are subscribed to the Google Groups "flint-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flint-devel...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/flint-devel/ae9884d3-90c9-44bb-87a3-a1a1706c94f8n%40googlegroups.com.

Hartmut Monien

unread,
Jul 29, 2024, 12:14:28 PM7/29/24
to flint-devel
Hello Frederic, 

The streams stdout in C and stdout in Haskell are not synchronized in the Foreign Function Interface (FFI).
The surprising fact is that 

-- | /gr_ctx_println/ /ctx/
gr_ctx_println :: Ptr CGRCtx -> IO GRStatus
gr_ctx_println ctx = do
  alloca $ \cs -> do
    status <- gr_ctx_get_str cs ctx
    h <- peek cs
    s <- peekCString h
    putStrLn s
    free (castPtr h)
    return gr_success

works, but 

-- | /gr_println/ /x/ /ctx/
gr_println :: Ptr CGR  -> Ptr -> CGRCtx -> IO GRStatus
gr_println x ctx = do
  alloca $ \cs -> do
    status <- gr_get_str cs x ctx
    h <- peek cs
    s <- peekCString h
    putStrLn s
    free (castPtr h)
    return gr_success

does not! The second corrupts the memory of x. I am still searching where this exactly happens ... . 

Cheers, 

HM

Hartmut Monien

unread,
Aug 8, 2024, 5:49:31 AM8/8/24
to flint-devel
It turned out to be an allocation error which had non-local effects ... . All works now.
Reply all
Reply to author
Forward
0 new messages