size_t

david.f.prosser dfp at cbnewsl.ATT.COM
Wed Jul 12 00:54:08 AEST 1989


In article <149 at ssp1.idca.tds.philips.nl> roelof at idca.tds.PHILIPS.nl (R. Vuurboom) writes:
>In article <1003 at cbnewsl.ATT.COM> dfp at cbnewsl.ATT.COM (david.f.prosser) writes:
>>In article <971 at tukki.jyu.fi> tarvaine at tukki.jyu.fi (Tapani Tarvainen) writes:
>>>Something related which I would call a bug is the behaviour of
>>>calloc() that e.g., calloc(1000,1000) won't give an error or NULL but
>>>silently truncates the product to 16960 (== 1000000 && 0x0ffff) and
>>>allocates that amount.  What does the pANS say about overflow handling
>>>in this situation?
>>>-- 
>>
>>There is a general statement in section 4.1.6 for the arguments to the
>>library functions.  It allows undefined behavior in the library if a
>>function is passed arguments with invalid values, or values outside of
>>the function's domain.  
>
>True but not particularly relevant (me thinks) since each argument _is_
>valid and well within (I hope!) the domain that size_t can handle.

True, each argument value is within the range of values representable by
size_t, but that's not sufficient in this case.

>
>>Since calloc() must produce an object with no more bytes than can be 
>>counted in a size_t, 
>
>Care to quote the relevant sentence? Doesn't seem to have made it into my
>Jan 88 draft :-).
>

I did slightly misstate the above.  Let me go into the argument in more
detail:

What you are probably looking for is a statement somewhere in the memory
allocation portion of the pANS (section 4.10.3) that explicitly requires
that any allocated object's size must be no bigger than can be sized by
size_t or that the multiplication of the arguments must not be bigger than
a size_t.  You won't find such simply because this is not the way the pANS
is written.  Instead, the pANS handles dynamically allocated objects just
the same as other objects, as much as possible.  The relevant part of the
pANS is that section 3.3.3.4 requires that the sizeof operator evaluate
to the size of its operand in bytes, and that the type of a sizeof
expression is an unsigned integral type--the same as the typedef size_t.

It is possible for calloc to allocate an object bigger than can be described
by size_t, but it is not required to do so, just as an implementation can
choose not to accept a request for a statically allocated object bigger than
can be described by size_t.  (There is a requirement that objects of at
least 32767 bytes must be accepted.)

As a consequence, a strictly conforming program cannot request an object
bigger than 32767 bytes.  Given the semantics of C, calloc(1000,1000) is
such a request.  (It takes a bunch of references before this can be
fully supported, but I'm taking this as given for this discussion.)
Therefore, the portable domain of calloc has been left behind.  Since there
are no explicit statements that override the generic "behavior is undefined
given out-of-bounds arguments" for calloc, an implementation has no
behavior constraints.  In fact, a valid implementation can "choose" to
"core dump" when the multiplication overflows in calloc!

Thus, my statement that calloc cannot allocate an object larger than can
be sized by size_t was inaccurate: a strictly conforming program cannot
attempt to allocate an object bigger than size_t as in the example because
the behavior of the library is undefined.

>
>Quoting from the Mark Williams Ansi C - A lexical guide:
>
>calloc allocates a portion of memory large enough to hold count items,
>each of which is size bytes long. It then initializes every byte within
>the portion to zero.
>
>calloc returns a pointer to the portion allocated. The pointer is aligned for
>any type of object. If it cannot allocate the amount of memory requested,
>it returns NULL.

This is a how calloc must behave when given strictly conforming argument
values.  Since calloc(1000,1000) cannot be part of a strictly conforming
program, the implementation can choose to behave in virtually any manner,
including exec'ing "rogue", as has been noted in earlier postings.

>
>My guess is that the above implementation is broken.
>
>In the above case, if you're using calloc to allocate memory for an array then
>you can't use sizeof to find the size of your array (in bytes) since sizeof 
>returns size_t. Could this be the source of confusion?

In any strictly conforming program, sizeof *must* be able to return the
number of bytes in *any* object.  The pANS only describes the behavior of
strictly conforming programs, and translators that accept all strictly
conforming programs.  Since, as I have argued above, a program that contains
a call to calloc(1000,1000) that is executed is not strictly conforming,
the pANS does not constrain calloc's behavior.

>
>>Dave Prosser	...not an official X3J11 answer...
>
>Roelof Vuurboom ...still not an official X3J11 answer...
>-- 
>Roelof Vuurboom  SSP/V3   Philips TDS Apeldoorn, The Netherlands   +31 55 432226
>domain: roelof at idca.tds.philips.nl             uucp:  ...!mcvax!philapd!roelof

All of this does not mean that I believe that calloc(1000,1000) should "not
work"; this has all been in the realm of what does the pANS require if
calloc(1000,1000) occurs.  Moreover, as the argument hinges on the less than
strictly conforming nature of the call, and since everything except the
result of the multiplication is strictly conforming, the argument may well
be tenuous.  I, nevertheless, am sticking by my guns.

Dave Prosser	...not an official X3J11 answer... (of course)



More information about the Comp.std.c mailing list