| To: | gwc@xxxxxxxxxxxxx, austin-group-l@xxxxxxxxxxxxx |
|---|---|
| Subject: | Re: [1003.1(2008)/Issue 7 0000177]: mismatch between example descriptionand code |
| From: | shwaresyst@xxxxxxx |
| Date: | Thu, 05 Nov 2009 11:24:15 -0500 |
| References: | <ee3ffd5cb61c11046aea665c63c5adbd@xxxxxx> <8CC2B9DD22E07E8-AF4-14C01@webmail-m088.sysops.aol.com> <20091105102458.GA11253@xxxxxx> |
|
1. is the most important part, actually. The original report was that the example didn't take into account that it's the application's responsibility to allocate the extra char for the appended null char, and the example as written possibly wouldn't read a full LINE_MAX chars as described in limits.h as a result of using just it as the argument to fgets(). This is less an issue with strtok() as it is listed as overwriting the seperator char found with a null, not appending it after. 2. {LINE_MAX} is in the class of variables that aren't allowed to return -1 from sysconf(). In the absence of a larger value set at runtime it is required to return the static LINE_MAX from limits.h, which in turn is required to be >= _POSIX2_LINE_MAX, so the test on sysconf()'s return is superfluous. As it's simple enough, I believe below adequately addresses being reasonably robust and shows the NULL is accounted for. Adding the partial line processing I believe would overly obfuscate the call setup requirements the example was intended to show, so replacing the ellipsis in the while loop with code of that nature is more a subject for a separate tutorial example and I've inserted descriptive comments in their place of possible caveats. fp is made an argument so the open/close call logic can be relegated to the calling code and the non-void return type is for reporting error codes. Mark <pre> #include <limits.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> int f(FILE *fp) { long line_max; /* used to avoid multiple sysconf() calls */ char *line; /* the buffer */ /* declare other variables function needs */ /* get implementation instance's max expectable line length and account for fgets() appending a NULL char */ line_max = sysconf(_SC_LINE_MAX) + 1; line = malloc(line_max); /* get the buffer space */ if (line=NULL) return ENOMEM; /* error check required by malloc() */ /* set up other declared variables needed for the loop's processing */ while (fgets(line, line_max, fp) != NULL) { /* process returned full or partial line, accounting for there may be embedded NULL chars along with the appended one; assumes fgets result = line when non-NULL */ }; /* process possible fgets error values returned in errno and handle normal EOF condition */ free(line); /* clean up the dynamic memory usage */ return 0; /* function succeded */ } </pre> -----Original Message----- From: Geoff Clare <gwc@xxxxxx> To: austin-group-l@xxxxxx Sent: Thu, Nov 5, 2009 5:24 am Subject: Re: [1003.1(2008)/Issue 7 0000177]: mismatch between example description and code shwaresyst@xxxxxx <shwaresyst@xxxxxx> wrote, on 04 Nov 2009: ---------------------------------------------------------------------- (0000278) nick (manager) - 2009-11-04 18:56 http://austingroupbugs.net/view.php?id=177#c278 ----------------------------------------------------------------------
Problem: line_max is declared as long. To use it as the array limit sysconf() couldn't be used to assign its runtime value. Suggested fix: change the line[line_max] declaration to 'char *line;' declaration with a malloc()/free() pair to assign line a value.
C99 allows variable-length arrays in some circumstances. I think
this one is valid (at least, it is accepted by gcc -std=c99 and
by the Sun Studio compiler when invoked as c99).
However, since line_max could potentially be very large, it would
be better to use malloc() so that if insufficient memory is
available the program will see an error returned by malloc()
instead of just crashing.
The code does have a couple of problems:
1. The size of line[], and the argument to fgets(), should be line_max+1
2. If sysconf() returns -1 to indicate that LINE_MAX is indeterminate
then setting line_max to the LINE_MAX macro from <limits.h> is the
wrong thing to do. It would mean that the fgets() loop needs to
handle partial lines, but the whole point of using a buffer sized
to {LINE_MAX} is so that the program doesn't need to handle partial
lines in the fgets() loop (except perhaps to detect them and report
that the input is not a text file).
One way to fix it would be to abandon the use of LINE_MAX altogether.
Just have a fixed size buffer (of, say, 4096 bytes) and show how to
handle partial lines in the fgets() loop. Alternatively, have the
code use getline() if sysconf() returns -1 and fgets() otherwise.
--
Geoff Clare <g.clare@xxxxxx>
The Open Group, Thames Tower, Station Road, Reading, RG1 1LX, England
|
| Previous by Date: | [1003.1(2008)/Issue 7 0000073]: wmemcmp C conflict?, Austin Group Bug Tracker |
|---|---|
| Next by Date: | [1003.1(2008)/Issue 7 0000167]: getenv() and modifying environ directly, Austin Group Bug Tracker |
| Previous by Thread: | Re: [1003.1(2008)/Issue 7 0000177]: mismatch between exampledescription and code, Geoff Clare |
| Next by Thread: | Re: [1003.1(2008)/Issue 7 0000177]: mismatch between example descriptionand code, wollman+austin-group |
| Indexes: | [Date] [Thread] [All Lists] |