Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: sizeof object got by dereferencing uniniitalized pointer Date: Fri, 29 Nov 2019 07:39:34 -0800 Organization: A noiseless patient Spider Lines: 71 Message-ID: <86k17i7kuh.fsf@linuxsc.com> References: <21e377ab-2a49-4f7e-bc18-72f1cee63204@googlegroups.com> <9d5ee6d4-607b-405f-83d9-afbe2b073cac@googlegroups.com> <76a74489-4a1f-4561-a01b-b2962a10bae4@googlegroups.com> <2119c5dc-fc01-4a74-93f4-8027c7cc210e@googlegroups.com> <43093894-ed52-47de-85f4-eadd92a1499e@googlegroups.com> <877e3j52do.fsf@bsb.me.uk> <86eexr8qlh.fsf@linuxsc.com> <87v9r33211.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="81b92e3fa8397acac1ab5cf195ff75cd"; logging-data="1626"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1916qHQmrXYwz6R/pLVVm4nvQhmzk6cqjw=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:TxdaM7KuM/5/5kLtqgYXfZdTKzM= sha1:cEwrwFR9TSkFHjrn59pbyZtk7kg= Xref: csiph.com comp.lang.c:148295 Ben Bacarisse writes: > Tim Rentsch writes: > >> Ben Bacarisse writes: >> >>> Thiago Adams writes: >>> >>> >>>> Only when applied to variably types, sizeof is in runtime. >>>> >>>> int n = 10; >>>> >>>> int(*buf)[n] = malloc(sizeof(int) * n); >>> >>> Why would you not write >>> >>> int (*buf)[n] = malloc(sizof *buf); >>> >>> ? >> >> Perhaps because, technically speaking, the right-hand side here >> has undefined behavior? > > Yes, it has. That has always puzzled me. Do you think that this usage > was specifically being ruled out, or is it a casualty of having made an > overly simple decision[1]? I have now looked into this further and can offer a more informed answer. More below. > This whole areas makes me uneasy. I've never been able to find a > reasonable example where an expression operand of sizeof needs to be > evaluated[2] (as the standard mandates) but most compilers evaluate f in > > sizeof (int[f()]) > > despite the standard not explaining what it means to evaluate a type > (though its not hard to guess what is intended). Do the rules make > sense to you? [I note your comment about _Generic_ but taking > it out because it doesn't bear on what I have to say.] The rules now make sense to me. The authors wanted to be sure (or so I believe, in case that needs saying) that they didn't miss any corner cases, and so used general wording. They did think about needless evaluation in 'sizeof' operands, and the Standard does have a provision which talks about that; in fact that provision evolved while C99 was being written. (If anyone cares they might want to compare n869 to later versions of the C99 standard.) Now, I hear you ask, _what_ corner cases? Here is one, taken from my recent reponse to Keith Thompson: int foo = sizeof *(int (*)[ ident( 1 ) ]){ &something }; This declaration is legal C99, provided of course there are suitable declarations for the identifiers 'something' and 'ident' in scope. The operand is an expression, not a type name, although of course the expression does have a type name within it. The operand expression needs to be evaluated, at least in part, in order to determine the result of the sizeof operator. Rather than concoct some carefully chosen language that does some sort of partial evalution for just those subexpressions that are needed to produce the result, the authors chose the simple rule that any VLA operand argument is evaluated. That decision has some unfortunate consequences for undefined behavior, but in the 1990s there wasn't as much hysteria regarding undefined behavior as there is now. So for better or worse there is my somewhat-more-informed current view of the matter.