Hi Zhiheng, On Thu, Apr 15, 2021 at 2:01 PM Zhiheng Li <phoenix_lzh@xxxxxxxx> wrote: > > Hello Alex, > > Section BUGS in setbuf.3 says the space that buf points must be exist at > program termination. And it says that the example is invalid. It wants > to express that the example cannot print "Hello, world!". Because the > stack space that buf points to is released when the program terminates > by return. > But the example prints "Hello, world!". So i say there is something > wrong with this example. > The original author should have made two mistakes: > 1. The typo of 'stdout'; > 2. The return is used. The original author did not know that the return > would close all file streams before terminating the program. Because > this program uses setbuf(3), the "Hello, world!" printed by printf(3) > will be saved in the buffer first. When the file stream is closed, buf > is exist, and the buffer is flushed, so the "Hello, world!" in the > buffer is printed(This knowledge comes from APUE 7.3). I've tried a slightly modified example on my Ubuntu 20.04 x86-64 VM (with just the stdout change but without _exit): #include <stdio.h> int main() { char buf[100]; setbuf(stdout, buf); printf("Hello, world\n!"); return 0; } I've built it with '-Wall -g'. I get garbage in the output: stefan@spuiu-vm:~/src/test/man_pages$ ./setbuf ���Ystefan@spuiu-vm:~/src/test/man_pages$ So I would say the buffer flushing happens outside of main(). If I remove the setbuf(), I see "Hello, world" printed as expected. I've also tried building with -O2 - it simply prints a different kind of garbage: stefan@spuiu-vm:~/src/test/man_pages$ ./setbuf ȿ Qstefan@spuiu-vm:~/src/test/man_pages$ So I would say the code is invalid as is (if stdout is used instead of stdin). Just my 2 cents, Stefan. > And returning an integer value from the main function is equivalent to > calling exit(3) with the same value(This knowledge also comes from APUE > 7.3). So return and exit(3) cannot be used. > _exit(3) and _Exit(3) terminate the program immediately, and they don't > close the file stream(This knowledge also comes from APUE 7.3), So using > _exit(3) and _Exit(3) does not print "Hello, world". > I'm using Thunderbird to send this email. It's very easy to use. Thank you. > > This is what I was going to send. When I was about to press the send > button, I thought again that it would be inappropriate to use _exit(2). > When using _exit(2), the file stream will not be flushed, but buf still > exists when the program terminates (the program terminates at the end of > main function, and buf exists at this time, which is in line with the > author's requirements, but the author wants to give a counter example). > So is the following example more appropriate? > #include <stdio.h> > void setmybuf(FILE *fp) > { > char buf[BUFSIZ]; > setbuf(fp, buf); > } > int main(void) > { > setmybuf(stdout); > printf("Hello, world!\n"); > return 0; > } > When the setmybuf returns, the buf stack space is released. When the > program close the file stream by return, buf does not exist for the main > function, which is in line with the author's original intention(This is > a invalid example). > Although the above program can still print "Hello, world!" in my > environment(ubuntu18.04, gcc5.5.0, glibc2.27), that's because the > address pointing to buf can still be used illegally(dangling pointer). > You can add some code to the source code to make the program produce > exceptions, like this: > #include <stdio.h> > void setmybuf(FILE *fp) > { > char buf[BUFSIZ]; > setbuf(fp, buf); > } > int test(int i) > { > if (i > 0) { > i--; > test(i); > } else { > printf("zzzzz\n"); > return 0; > } > } > int main(void) > { > setmybuf(stdout); > printf("Hello, world!\n"); > test(1000); > return 0; > } > Recursively called functions test use the stack space of buf in > setmybuf, which can cause segmentation fault in my evironment. > > > Sincerely, > Zhiheng Li > > > > On 4/12/21 5:22 PM, Alejandro Colomar (man-pages) wrote: > > On 4/12/21 9:44 AM, Zhiheng Li wrote: > >> --- > >> man3/setbuf.3 | 5 +++-- > >> 1 file changed, 3 insertions(+), 2 deletions(-) > >> > >> diff --git a/man3/setbuf.3 b/man3/setbuf.3 > >> index 5e5d57f89..e6d41b2a9 100644 > >> --- a/man3/setbuf.3 > >> +++ b/man3/setbuf.3 > >> @@ -224,14 +224,15 @@ For example, the following is invalid: > >> .PP > >> .EX > >> #include <stdio.h> > >> +#include <unistd.h> > >> int > >> main(void) > >> { > >> char buf[BUFSIZ]; > >> - setbuf(stdin, buf); > >> + setbuf(stdout, buf); > >> printf("Hello, world!\en"); > >> - return 0; > >> + _exit(0); > >> } > >> .EE > >> .SH SEE ALSO > >> > > > > Hello Zhiheng Li, > > > > I never used setbuf(3), so I don't know much about this example and why > > it is "invalid", and therefore also don't know why it is wrong in being > > invalid. > > > > As far as I can see, 'stdin' just seems to be a typo because it's not > > being used, and probably 'stdout' was meant instead, as you point out. > > > > What about _exit(0)? Why _exit(2) and not return (or equivalently > > exit(3))? Could you explain that a bit more? > > > > BTW, Could you please use a mailer that allows you to write plain text > > emails? Mozilla Thunderbird may be easy to use for you, and it comes > > with most Linux distros. > > > > Thanks, > > > > Alex > >