Who is the free setvbuf buffer?

So, I delved into how the libd lib part is implemented, and I came across another question. Looking at man setvbuf , I see the following:

When the first I / O operation occurs, the file, malloc (3), and the buffer are called.

That makes sense, your program should not have malloc in it for I / O unless you actually use it. My reaction to this is that libc will clear its own mess here. I can only assume that this is because valgrind does not report a memory leak (they could, of course, do something dirty and not distribute it directly through malloc ... but we will assume that it currently uses malloc )

But , you can also specify your own buffer ...

 int main() { char *p = malloc(100); setvbuf(stdio, p, _IOFBF, 100); puts("hello world"); } 

No memory leak! valgrind confirms this. Therefore, it seems that whenever stdio independently allocates a buffer, it is automatically deleted (no later than when exiting the program, but it may close in the stream). But if you explicitly specify a buffer, you must clear it yourself.

However, there is a trick. The man page also says the following:

You must make sure that the space, which by the time moment the thread is closed, which also occurs when the program ends. For example, the following is not valid:

Now it becomes interesting for standard streams. How to properly clear the manually allocated buffer for them, since they are closed at the end of the program? I could imagine โ€œclearing this when I close the flagโ€ inside the file structure, but it gets hairy, because if I read it correctly, we will do something like this:

 setvbuf(stdout, 0, _IOFBF, 0); printf("hello "); setvbuf(stdout, 0, _IOLBF, 0); printf("world\n"); 

will result in 2 allocations of the standard library due to this sentence:

If buf is NULL, only the mode is affected; a new buffer will be allocated on the next read or write operation.

EDIT: Adding to my question. Since it is clear that I should pass any buffers to setvbuf , if I really use it on stdout , is there any practical way to free it? He must live to complete the program. The best I can come up with is fclose(stdout) , then free it up or use the static buffer that some people talked about. I ask because it seems like an awkward design decision.

+7
c buffer stdio
source share
3 answers

Also from the man page (at least on my system):

If buf is not NULL, the responsibility for freeing (3) this buffer after closing the stream is the responsibility of the caller.

That is, you are malloc-ed, you are freeing it.

Before exiting, you can close the threads yourself, which will allow you to free the buffer. Alternatively, you can setvbuf threads and call setvbuf again with the NULL buffer argument to switch back to the library-driven buffer or unbuffered I / O.

+3
source share

At least according to the C standard, your last script is simply not allowed: "The setvbuf function can be used only after the stream pointed to by the stream is associated with an open file and before any other operation (except for an unsuccessful setvbuf call) is executed in the stream . " (C99, ยง7.19.5.6 / 2).

As for when to free memory in simpler cases, on the way you need to call atexit() to register a callback that will free the memory after exiting main() , but before control is returned to the OS.

+3
source share

You can close stdin , stdout and stderr explicitly (using fclose() ).

On most operating systems, heap memory is automatically issued after the program exits. So there is no practical problem with unreleased buffers (there is a cosmetic problem that these unreleased buffers pollute Valgrind output). My advice would be to use static buffers if you feel like calling setvbuf() on standard input or output. Static buffers do not need to be allocated or released, and here they are suitable, since there are only three standard threads, and you are worried about a situation where these threads remain open until the program terminates.

+1
source share

All Articles