Base WG Resolution Ref: bwg98-007
Topic: fwrite when size=0


This is an unapproved draft Base Working Group Resolution for XSH5.

Last update: 09 November,1998


                                                                98 #007

 _____________________________________________________________________________

                Topic:                  fwrite when size=0
                Relevant Sections:      fwrite
                Spec:                   XSH5

------------------------------------------------------------------------

Defect Report concerning (volume of the Single UNIX Specification):

System Interfaces & Headers Issue 5 (XSH5) [UNIX 98]

------------------------------------------------------------------------

Qualifier (e.g. error, omission, clarification required):

1

Error=1 , Omission=2, Clarification=3

------------------------------------------------------------------------

References in document (e.g. page, clause, figure, and/or table
numbers or URL if applicable):

http://www.opengroup.org/onlinepubs/7908799/xsh/fwrite.html

------------------------------------------------------------------------

Nature of defect (complete, concise explanation of the perceived
problem):


The return value for the case size=0, nitems>0 (e.g. fwrite(buf, 0, 1,
stream)) contradicts the ISO C specification, which states:

       [#3] The fwrite function  returns  the  number  of  elements
       successfully  written, which will be less than nmemb only if
       a write error is encountered.

Since no write error can occur if size equals 0, the ISO C
specification demands that fwrite(buf, 0, n, stream) returns n for any
n>=0.  The above URL of the Single Unix specification clearly indicates
that 0 should be returned.

The same contradiction appears in Single Unix's fread() specification,
even more clearly, because like the ISO C standard it states:

     fread() returns the number of
     members successfully read which is less than nitems only if a read
     error or end-of-file is encountered.

------------------------------------------------------------------------

Solution proposed by the submitter (optional):

A possible solution would be to adopt the ISO C wording for the return
values of fwrite() and fread(), and omitting the special case `If size
or nitems is 0 ...'.

------------------------------------------------------------------------

Proposed resolution.


The C standard is inconsistent regarding fread() and fwrite() when
size==0.  In fread(), there's an explicit sentence which specifies
that if either size or nmemb is 0 that the return value is zero, hence
the Single UNIX Specification fread() interface is aligned .  The
are of contention is the lack of an equivalent sentence in fwrite().
(a comment has been sent to the c9x committee).

All known UNIX implementations return 0 for both functions when
either size or nmemb is zero because the they essentially turn into
calls to read() or write() of size*nmemb bytes.  The C standard was
supposed to codify existing practice, and this looks like an ommision.

The current additional wording in the Single UNIX Specification is 
justified as follows:

First of all, the C standard does not acknowledge the possibility 
for a zero-sized object.  Nowhere does it require an implementation to 
accept such.

Arrays cannot have zero length.  Structures must have at least one
real (not :0) member.  malloc(0) has two different behaviors.  This
was a deliberate decision by the C committee.

Thus, passing size==0 to fwrite() is outside the bounds of the
standard, since the "Use of library functions" clause explicitly
says that "If an argument to a function has an invalid value (such
as a value outside the domain of the function, or a pointer outside
the address space of the program, or a null pointer), the behavior
is undefined."

For fread(), since the standard specifies a behavior when size==0,
that's okay, but for fwrite(), there is no requirement that the
function do anything reasonable at all.  The additional text in
the Single UNIX Specification of  fwrite() are providing a specification 
where the C standard had unbounded behavior.

Forwarded to Base group: Nov 9 1998