Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > malloc and maximum size

Reply
Thread Tools

malloc and maximum size

 
 
Ben Bacarisse
Guest
Posts: n/a
 
      10-15-2011
Keith Thompson <(E-Mail Removed)> writes:
<snip>
> In particular, I can argue that a conforming compiler can permit
>
> typedef char[2 * SIZE_MAX] way_too_big;


Irrelevant to your point, but you mean, I think,

typedef char way_too_big[2 * SIZE_MAX];

<snip>
--
Ben.
 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      10-15-2011
On 10/14/2011 06:42 PM, Lowell Gilbert wrote:
> James Kuyper <(E-Mail Removed)> writes:
>
>> On 10/14/2011 03:46 PM, Lowell Gilbert wrote:
>>> James Kuyper <(E-Mail Removed)> writes:
>>>
>>>> On 10/14/2011 03:00 PM, Lowell Gilbert wrote:

....
>>>>> For size_t, the type is just defined as the output type for sizeof,
>>>>> which is defined in turn as yielding the size of its operand. So I can
>>>>> see an argument that the "maximum value" of a size_t could be viewed as
>>>>> the largest value that sizeof could possibly yield on the particular
>>>>> implementation.


I realize now that I passed over the paragraph above without commenting
on it. I disagree with it's assertions. sizeof expressions have a type,
and size_t is a typedef for that type, but that's the definition of the
typedef, not the definition of the type. That type can be, and usually
is, a type that already can be named in some other manner by the user,
such as "unsigned long". It's defined in terms of it's properties, not
by the fact that one of the things it's used for is as the result type
of sizeof expressions. It must be suitable for such use, or the typedef
is inappropriate, but it's maximum value is a property of the type
itself, not a property of one particular use of that type.

>>>> Well, the maximum value returnable by sizeof has to be the same as the
>>>> maximum value representable by size_t:
>>>>
>>>> sizeof(char[(size_t)-1]) == (size_t)(-1)
>>>
>>> Assuming I understand what you're getting at, you're begging the
>>> question here. [But the expression doesn't make sense to me, so
>>> the assumption may well be wrong.]

>>
>> I had not intended to beg the question. Per 6.3.1.3p2, (size_t)(-1) is
>> precisely "the maximum value that can be represented" as a size_t.

>
> Then you were indeed begging the question; the equality is *exactly*
> what I'm questioning.


I don't see how "begging the question" comes into play. I thought the
truth of that equality was perfectly clear, and did not present a
detailed argument for it until after I realized that you disagreed.
However, in that argument, I did not assume that equality to be true, I
generated that conclusion from various more fundamental features of C.

>> char[(size_t)(-1)] is an array type whose size in bytes is (size_t)(-1).
>> sizeof(char[(size_t)(-1)]) must therefore yield a value which is
>> (size_t)(-1). Therefore, the largest value that sizeof could possibly
>> yield must be (size_t)(-1), the same as the maximum representable value.

>
> I see; I was assuming you were giving a C expression, since it looked
> like one. Thanks for the explanation.


Yes, your assumption was correct, sizeof(char[(size_t)(-1)]) is indeed a
C expression.

Keith has already addressed your other points, though not exactly in the
fashion that I would have. It will simplify things if I respond to his
message, rather than yours.
--
James Kuyper
 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      10-15-2011
On 10/14/2011 07:27 PM, Keith Thompson wrote:
....
> C99 5.2.4.1 discusses translation limits (127 nesting levels of blocks,
> 63 nesting levels of conditional inclusion, etc.). It requires an
> implementation to accept 65535 bytes in an object, but that doesn't
> apply to the above expression, since it doesn't refer to an object.
>
> On the other hand, 5.2.4.1 doesn't even say that an implementation
> must always accept 65535 bytes in an object. It says:
>
> The implementation shall be able to translate and execute at least
> one program that contains at least one instance of every one of the
> following limits:
>
> followed by a list of limits. By rejecting "sizeof(char[3500000000])",
> gcc isn't violating any requirement in 5.2.4.1; presumably it does
> translate and execute that one program (which doesn't include an
> instance of "sizeof(char[3500000000])".
>
> Presumably an implementation may legitimately reject a program violating
> some limit not listed in 5.2.4.1, such as a trillion-line translation
> unit. So I *think* that rejecting any program referring to a type
> bigger than 2**31 bytes is permitted. But I'm not 100% certain.


As I'm sure you're already aware, 5.2.4.1 is one of my least favorite
clauses in the standard. Taking it's words literally, what it fails to
promise renders virtually the entire rest of the standard meaningless;
this is just one example of that fact. Except when I'm arguing against
someone who disagrees on that point, I generally prefer to pretend that
5.2.4.1 says something that allows the rest of the standard to be
meaningful.

In this particular case, I'd prefer to believe that the standard's
requirement that sizeof(type) yield the size of the specified type
(6.5.3.4p2) always applies, except when it's impossible for it to do so,
because the size is too big to be represented by a size_t.
sizeof(char[(size_t)(-1)]) can be represented by a size_t, so it should
not be exempted from that requirement. I will, however, reluctantly
agree that the standard is not clear on that point.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      10-15-2011
On 10/14/2011 08:41 PM, Richard Damon wrote:
> On 10/14/11 7:27 PM, Keith Thompson wrote:
>>
>> What (arguably) requires the implementation to accept
>> "sizeof(char[3500000000])" is the same thing that requires it to
>> accept "sizeof(char[10])", namely the sections discussing the sizeof
>> operator, the char type, integer constants, and array types.
>>

>
> Why should the compiler be forced to allow the definition of a type that
> defines an object bigger than is allowed??


No type was defined by that expression.

> Note that all valid object sizes must fit within a size_t,


More accurately, all sizeof expressions must have a result that fits
within a size_t. That's true whether they have a type argument or an
expression argument. It's true whether their expression argument is an
lvalue or an rvalue. It's true whether or not there's any actual object
referred to by the lvalue expression that is their argument.

It's also, apparently, true whether or not it's actually possible for
the size to be represented by a size_t, because the standard specifies
no exemption from that requirement just because it can't be met. By my
standards that constitutes a defect in the standard.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      10-15-2011
On 10/14/2011 07:03 PM, Keith Thompson wrote:
....
> Interesting. For the following program:
>
> #include <stdio.h>
> int main(void) {
> printf("%zu\n", sizeof (char[(size_t)-1]));
> return 0;
> }
>
> "gcc -std=c99" rejects it with an error message:
>
> c.c: In function ‘main’:
> c.c:3:5: error: size of unnamed array is too large
>
> Change the array size to (size_t)-1/2 and it compiles and prints
> "2147483647". Change it to (size_t)-1/2+1 and it rejects it with the
> same error message.
>
> Does this make "gcc -std=c99" non-conforming?


I've argued that such behavior would make it non-conforming, but the
implementation-limits issue is sufficiently foggy that it's not at all
clear.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      10-15-2011
On 10/14/2011 07:12 PM, Keith Thompson wrote:
> James Kuyper <(E-Mail Removed)> writes:

....
>> If you're talking about an implementation where size_t is a 24-bit
>> unsigned integer implemented using 24 value bits and 8 padding bits,
>> then SIZE_MAX could be be 0xFFFFFFFFFFFFF.

>
> Do you mean 0xFFFFFF?
>
>> However, that requires that
>> emulation of a 24-bit type be performed correctly: (size_t)(-1) has to
>> be SIZE_MAX, and size_t_expression & 0xFFFF000000000000

>
> 0xFF000000?


I spent a lot of time recently writing code with hex masks for 64 bit
types. The shorter, correct versions you've give above didn't look right
- they were too short.
--
James Kuyper
 
Reply With Quote
 
Richard Damon
Guest
Posts: n/a
 
      10-15-2011
On 10/14/11 10:59 PM, James Kuyper wrote:
> On 10/14/2011 08:41 PM, Richard Damon wrote:
>> On 10/14/11 7:27 PM, Keith Thompson wrote:
>>>
>>> What (arguably) requires the implementation to accept
>>> "sizeof(char[3500000000])" is the same thing that requires it to
>>> accept "sizeof(char[10])", namely the sections discussing the sizeof
>>> operator, the char type, integer constants, and array types.
>>>

>>
>> Why should the compiler be forced to allow the definition of a type that
>> defines an object bigger than is allowed??

>
> No type was defined by that expression.
>
>> Note that all valid object sizes must fit within a size_t,

>
> More accurately, all sizeof expressions must have a result that fits
> within a size_t. That's true whether they have a type argument or an
> expression argument. It's true whether their expression argument is an
> lvalue or an rvalue. It's true whether or not there's any actual object
> referred to by the lvalue expression that is their argument.
>
> It's also, apparently, true whether or not it's actually possible for
> the size to be represented by a size_t, because the standard specifies
> no exemption from that requirement just because it can't be met. By my
> standards that constitutes a defect in the standard.


If there exists a type/object whose size can not be expressed by sizeof,
then the compiler is going to be obligated to generate a diagnostic and
fail to compile the program. If it doesn't, it can't meet the
requirements of the standard. If it allowed the type/object to exist,
then it is going to need to rely on the ability to fail for exceeding an
implementation limit.

Due to the various problems that arise by having objects bigger than can
be expressed by size_t, it is better for the compiler to generate the
diagnostic on attempting to create the enormous type rather than wait
for the user to apply sizeof to it.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-15-2011
Ben Bacarisse <(E-Mail Removed)> writes:
> Keith Thompson <(E-Mail Removed)> writes:
> <snip>
>> In particular, I can argue that a conforming compiler can permit
>>
>> typedef char[2 * SIZE_MAX] way_too_big;

>
> Irrelevant to your point, but you mean, I think,
>
> typedef char way_too_big[2 * SIZE_MAX];
>
> <snip>


Yes, thanks.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-15-2011
James Kuyper <(E-Mail Removed)> writes:
[...]
> As I'm sure you're already aware, 5.2.4.1 is one of my least favorite
> clauses in the standard. Taking it's words literally, what it fails to
> promise renders virtually the entire rest of the standard meaningless;
> this is just one example of that fact. Except when I'm arguing against
> someone who disagrees on that point, I generally prefer to pretend that
> 5.2.4.1 says something that allows the rest of the standard to be
> meaningful.

[...]

The problem is that compilers can run out of resources in a plethora
of circumstances, and it's difficult or impossible to define a
coherent set of criteria such that you can reasonably require *all*
programs that meet those criteria are "small" enough that we can
expect all compilers to accept them.

I find 5.2.4.1 a clever way to deal with it. An implementation
*could* satisfy the rather oddly stated requirement by cheating
(recognizing one specific program that meets all the limits and
does nothing, and treating it as `int main(void) { }"). But in the
absence of that, the easiest way to satisfy 5.2.4.1 is probably to
write a compiler that doesn't impose any fixed limits (as suggested
by the footnote).

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-15-2011
Richard Damon <(E-Mail Removed)> writes:
> On 10/14/11 10:59 PM, James Kuyper wrote:
>> On 10/14/2011 08:41 PM, Richard Damon wrote:

[...]
>>> Note that all valid object sizes must fit within a size_t,

>>
>> More accurately, all sizeof expressions must have a result that fits
>> within a size_t. That's true whether they have a type argument or an
>> expression argument. It's true whether their expression argument is an
>> lvalue or an rvalue. It's true whether or not there's any actual object
>> referred to by the lvalue expression that is their argument.
>>
>> It's also, apparently, true whether or not it's actually possible for
>> the size to be represented by a size_t, because the standard specifies
>> no exemption from that requirement just because it can't be met. By my
>> standards that constitutes a defect in the standard.

>
> If there exists a type/object whose size can not be expressed by sizeof,
> then the compiler is going to be obligated to generate a diagnostic and
> fail to compile the program. If it doesn't, it can't meet the
> requirements of the standard. If it allowed the type/object to exist,
> then it is going to need to rely on the ability to fail for exceeding an
> implementation limit.


An implementation is *never* required to fail to compile a program
unless it contains a "#error" directive. Violations of syntax rules and
constraints require a diagnostic; once the diagnostic is issued, the
behavior is undefined.

But do you mean that a diagnostic is required even if the program
doesn't invoke sizeof? What requirements can't it meet?

> Due to the various problems that arise by having objects bigger than can
> be expressed by size_t, it is better for the compiler to generate the
> diagnostic on attempting to create the enormous type rather than wait
> for the user to apply sizeof to it.


C99 6.5p5:

If an _exceptional condition_ occurs during the evaluation of
an expression (that is, if the result is not mathematically
defined or not in the range of representable values for its
type), the behavior is undefined.

I think that applies to "sizeof" as much as it applies to "+".
Which means that a program that evaluates "sizeof (char[SIZE_MAX+1])"
has undefined behavior; no diagnostic is required.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Creating the maximum number of menus and maximum number of stills rossco DVD Video 2 11-24-2005 09:33 PM
the maximum memory size allowed in malloc Jerry C Programming 19 01-27-2005 12:12 AM
free'ing malloc'd structure with malloc'd members John C Programming 13 08-02-2004 11:45 AM
The number name 'System.Web.UI.WebControls' contains more than the maximum number of prefixes. The maximum is 3. mayur ASP .Net Web Controls 2 07-16-2004 05:14 PM
The number name 'System.Web.UI.WebControls' contains more than the maximum number of prefixes. The maximum is 3. mayur ASP .Net 2 07-02-2004 10:35 AM



Advertisments