Email List: Xaustin-group-lX
[All Lists]

Re: [1003.1(2008)/Issue 7 0000177]: mismatch between exampledescription

To: austin-group-l@xxxxxxxxxxxxx
Subject: Re: [1003.1(2008)/Issue 7 0000177]: mismatch between exampledescription and code
From: Geoff Clare <gwc@xxxxxxxxxxxxx>
Date: Thu, 5 Nov 2009 10:24:58 +0000
References: <ee3ffd5cb61c11046aea665c63c5adbd@austingroupbugs.net> <8CC2B9DD22E07E8-AF4-14C01@webmail-m088.sysops.aol.com>
shwaresyst@aol.com <shwaresyst@aol.com> wrote, on 04 Nov 2009:
>
>> ----------------------------------------------------------------------
>> (0000278) nick (manager) - 2009-11-04 18:56
>> http://austingroupbugs.net/view.php?id=177#c278
>> ----------------------------------------------------------------------
>> A better example:
>>
>> <pre>
>> #include <stdio.h>
>> #include <limits.h>
>> #include <unistd.h>
>>
>> void f()
>> {
>>    long line_max;
>>    FILE *fp;
>>        ...
>>    if ((line_max = sysconf(_SC_LINE_MAX)) <= 0) {
>>        line_max = LINE_MAX;
>>    }
>>    char line[line_max];
>>    while (fgets(line, line_max, fp) != NULL) {
>>        ...
>>    }
>>    return;
>> }
>>
>> </pre>

> Problem: line_max is declared as long. To use it as the array limit  
> declarator it would have to be '#define line_max =0;' but then 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@opengroup.org>
The Open Group, Thames Tower, Station Road, Reading, RG1 1LX, England

<Prev in Thread] Current Thread [Next in Thread>