Path: csiph.com!3.us.feeder.erje.net!feeder.erje.net!news.linkpendium.com!news.linkpendium.com!news.snarked.org!border2.nntp.dca1.giganews.com!nntp.giganews.com!news.iecc.com!.POSTED.news.iecc.com!nerds-end From: Andy Walker Newsgroups: comp.compilers Subject: Re: Bounds checking, Optimization techniques and undefined behavior Date: Wed, 8 May 2019 01:42:31 +0100 Organization: Not very much Lines: 61 Sender: news@iecc.com Approved: comp.compilers@iecc.com Message-ID: <19-05-058@comp.compilers> References: <19-04-021@comp.compilers> <19-04-023@comp.compilers> <19-04-037@comp.compilers> <19-04-039@comp.compilers> <19-04-042@comp.compilers> <19-04-044@comp.compilers> <19-04-047@comp.compilers> <19-05-004@comp.compilers> <19-05-006@comp.compilers> <19-05-016@comp.compilers> <19-05-020@comp.compilers> <19-05-024@comp.compilers> <19-05-025@comp.compilers> <19-05-028@comp.compilers> <19-05-029@comp.compilers> <19-05-034@comp.compilers> <19-05-045@comp.compilers> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Info: gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="97477"; mail-complaints-to="abuse@iecc.com" Keywords: standards, errors, optimize, comment Posted-Date: 07 May 2019 22:53:09 EDT X-submission-address: compilers@iecc.com X-moderator-address: compilers-request@iecc.com X-FAQ-and-archives: http://compilers.iecc.com Content-Language: en-GB Xref: csiph.com comp.compilers:2293 On 07/05/2019 10:04, David Brown wrote: > It will not be slower in C - because the compiler knows that "i" is > never changed in the loop. (I'd like some way to have that enforced in > C, but I don't know of any good method.) There's rather little you can "enforce" in C unless the compiler is on your side! See below. > Just for a laugh, try this code: [largely snipped for brevity -- ANW] > #include > int *pi = &i; > int *pj = &j; > printf("pi = %p, pj[-1] = %p\n", [...] There is sanction in the Standard for adding one to a pointer to a scalar, but not for subtracting one; so this is UB [N1570, section 6.5.6, paras 7, 8]. > [...] With no optimisation and a literal translation of > the code, the result will be 48. Yes, provided that the compiler doesn't enforce the Standard! > With optimisation, the compiler knows > that access through "pj" cannot possibly affect "i" without invoking > undefined behaviour - so it can simplify the loop to "sum = 55;" and > shows that result. Quite. That's the sort of way that UB comes back to bite you. You optimise some code, and the answer changes. There are worse possibilities, even without going beyond reasonableness; take, for example Bart's "struct" with four integer members that he wants to treat as an array. Suppose further that he tries to write to the i'th member of that array, even after checking that 0 <= i <= 3. A non- checking compiler will allow that, even though it's UB if i > 0. An optimising compiler may quite well, however, deduce that "therefore" i = 0, and carry that value of "i" forward in the analysis. If the decision whether or not to "rm -rf /" depends on the value of "i", you can be well and truly up the creek without a paddle. [Moderator:] > [For the loop with the unchangable index, you can declare the index > const and cast the places you change it, [...]. As so often, you may well get away with it, but it's UB. See in particular footnote 132 -- " The implementation may place a const object that is not volatile " in a read-only region of storage. " Further, if you can change the index that way, so can a malicious or careless writer of the loop body, which rather negates the point of making it "const". To do it properly, it needs to be a defined and checkable property in the language, as in, for example, Algol 68. -- Andy Walker, Nottingham. [Hey, I said "but ugh". I would think that an auto const without a constant initializer wouldn't be eligible for read-only storage since it might have a different value each time the block is entered. -John]