bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: source(builtin) and read(2)


From: Geoff Clare
Subject: Re: source(builtin) and read(2)
Date: Fri, 30 Mar 2007 23:22:14 +0100
User-agent: Mutt/1.5.9i

Paul Eggert <address@hidden> wrote, on 30 Mar 2007:
>
> Geoff Clare writes:
> 
> > If the following code:
> >
> >    ssize_t var;
> >    var = SSIZE_MAX;
> >    ++var;
> >    if (var > SSIZE_MAX)
> >     puts("SSIZE_MAX wrong");
> >
> > outputs "SSIZE_MAX wrong" on any implementation, then var is an object
> > of type ssize_t which was able to contain a value greater than
> > SSIZE_MAX, and therefore the implementation's definition of SSIZE_MAX
> > does not conform to the standard.
> 
> That's not the case, and this indicates how murky the waters are in
> this area.  In C, that "++var" has undefined behavior, and a
> conforming implementation can therefore do anything it likes with this
> example, which means it can indeed print "SSIZE_MAX wrong".

Picky, picky.  Let me restate it as "if the code ... outputs
"SSIZE_MAX wrong" (through normal execution, not undefined behaviour),
then ..."

The code was just to illustrate the point that if it is possible for
the condition (var > SSIZE_MAX) to be true then the implementation
does not conform to the requirement that SSIZE_MAX is the maximum
value of an object of type ssize_t.

> 
> > The ssize_t type was introduced (in 1990) in order to allow read()
> > and write() to read and write more than INT_MAX bytes.  This is clear
> > from the rationale for read():
> 
>    "The use of I/O with large byte counts has always presented
>     problems. Ideas such as lread() and lwrite() (using and returning
>     longs) were considered at one time. The current solution is to
>     use abstract types on the ISO C standard function to read() and
>     write(). The abstract types can be declared so that existing
>     functions work, but can also be declared so that larger types can
>     be represented in future implementations.
> 
> But that rationale can be interpreted a different way.  Suppose it's
> 1990 and we have a new machine with 32-bit int and 64-bit size_t, with
> a traditional 'read' that returns 'int' so its result is limited to 32
> bits.  We define ssize_t to be 64 bits because we want to fix this
> while we adjust our machine to conform to POSIX (this doesn't break
> the API since 'int' is the lower half of a 64-bit register), but in
> the meantime we're stuck with a large body of code that uses 'int' and
> assumes a 32 bit maximum.  On this implementation ssize_t would be 64
> bits wide, but SSIZE_MAX would be 2**31 - 1.

I doubt very much if 32-bit int and 64-bit size_t was considered.
The whole point, surely, was to allow implementations with 16-bit
int to read and write more than 32K bytes.

You also left off the last part of the rationale I quoted:

    "This volume of IEEE Std 1003.1-2001 also limits the range further
    by requiring that the byte count be limited so that a signed
    return value remains meaningful. Since the return type is also a
    (signed) abstract type, the byte count can be defined by the
    implementation to be larger than an int can hold."

It was that part ("larger than an int can hold") which made the reason
for changing the return type of read() to ssize_t particularly clear.
With your example of 32-bit int, 64-bit size_t, and SSIZE_MAX = 2**31-1,
SSIZE_MAX is not larger than an int can hold.

-- 
Geoff Clare <address@hidden>
The Open Group, Thames Tower, Station Road, Reading, RG1 1LX, England




reply via email to

[Prev in Thread] Current Thread [Next in Thread]