Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Safe & correct versions of procuall, proclos
Hi Christof, Thanks for your feedback! I agree that writing safe C is hard, I find it quite a fun exercise though. It's also fun to see how engaged people get when talking about some of these problems. > >There are a couple of problems in your code: > >1. you don't free the "out" and "line" buffers. Yep, the fact that the program is just a one-shot test that exits immediately meant that I was less worried about memory leaks. > >2. actually, there is no reason to malloc "out" in the first place; just >put the array on the stack with "char out[MAXLINE];" This is a valid point, actually stack allocation works fine for both "fname" and "out". >3. I'm not sure why you are calling "fileno" and "fstat". You don't seem >to use the result, so maybe you're just checking whether the file >exists? In that case, "fopen" would have failed already. Just seems >entirely redundant to me Ok, so I understand your confusion. The program is written to help me better understand a particular type of error - attempting a read of a "proc" pseudo file after the process has disappeared. The calls to "fileno" (to get the file descriptor) and "fstat" to initialize the "struct stat sb" are only interesting in the case that the program succeeds. They're not really "doing" anything as such, just included to indicate that a real program would presumably go off and do some work after the fopen call. It should be possible to run the program successfully with "./proclos $$ 1" > >4. "sprintf" is unsafe, always use "snprintf" instead! Thanks for the tip! > >5. "sprintf" (and "snprintf") already return the number of written >characters - no need for "strlen(out)"! Cheers. > >6. You never call "fclose" Changed this. > >7. There's is no proper cleanups on early returns Yeah, so I think this should be better in the corrected version. Actually, I had already implemented this in "procuall" yesterday, but of course Murphy's law meant that you looked at the other program! > >8. Instead writing to a string buffer with "sprintf" and then writing >that buffer to stdout with "fwrite", you could just use "fprintf" :) Yep, this also makes much more sense. I think I was just copy-pasta-ing from the getline example in the linux man pages. > >I was only looking at "proclos.c". I assume "procuall.c" has similar errors. Yeah, I had started to address the issues around cleanup in "procuall.c". Anyway, both versions have now included your suggestions and I'm happy to report both are leak-free! > >Writing proper C is *hard*, in particular error handling and resource >cleanup. That's where C++'s RAII really shines. I found that writing a lot of assembly helped to understand better how to use "goto" statements for this type of thing. It's amazing how much easier it is to write high level languages after wrestling with this type of problem. I haven't written any C++ recently, part of me is itching to try out either Rust or Zig though. > >It's a good exercise, though! >
- Loading branch information