C23 reference links
C23 reference links
Posted Jul 24, 2024 16:56 UTC (Wed) by mb (subscriber, #50428)In reply to: C23 reference links by khim
Parent article: GNU C Library 2.40 released
They *do* behave differently. That's what the reality looks like.
>C23 may easily specify one way that is supported and make others behave in the same way.
Changing the behavior would very likely break existing non-portable programs.
There are only two realistic options: Make it implementation defined or undefined.
Posted Jul 24, 2024 17:18 UTC (Wed)
by khim (subscriber, #9252)
[Link] (7 responses)
None of these programs are C23-compliant, anyway, so that's a moot point. Or keep it like it was in C17. If developers may cope with two decades of non-decision for important matters then why couldn't they live without sane resolution for some fringe and not too interesting case? And between bad, worse and worst choices… worst was picked — why exactly?
It's really one of the craziest cases of “we have to do something… this is something… then let's do it!”
Posted Jul 24, 2024 19:42 UTC (Wed)
by farnz (subscriber, #17727)
[Link] (6 responses)
Keeping it like it was in C17 is making it undefined behaviour, just with obfuscated language to hide that from people who don't spend all their time following through the implications of standardese. If the C17 definition was OK, then simplifying the language used to define it but keeping the definition the same should also be OK.
It would have been better to redraft the C17 language so that you couldn't select the set of options that make it UB, but that's not what the committee chose to do - in large part (as far as I can tell as a non-attendee) because any attempt to change the allowed set of options upset people who felt that other people were Wrong to implement realloc(_, 0) the way they did. Rather than continue trying to find some way to make it work for two groups who refuse to agree, the wording just got simplified to remove the long chain of logic leading to it being UB, since the two conflicting groups can just as easily define it downstream if they care.
Posted Jul 24, 2024 20:48 UTC (Wed)
by khim (subscriber, #9252)
[Link] (5 responses)
Tell me what gives compiler writer the right to turn this function:
into empty sequence of instructions (without even Only if you explain how the optimization described above is allowed. I coudn't see how C17 may allow that. C23, most definitely, makes it Ok. And, instead, they have picked an approach which would make every single one of these people ask about sanity of people who pushed this approach to the language. Is it really an improvement? Except we already know where that leads: no one would bother to do anything, but compiler writers, few years down the road, would interpret the wording in the most ruinous way possible. That decisions would be funny if not for the past experience with this exact function.
Posted Jul 24, 2024 22:40 UTC (Wed)
by farnz (subscriber, #17727)
[Link] (4 responses)
It's a nasty little mistake in drafting, in paragraph 3 of 7.22.3.5, and clearly a defect. However, the standard only imposes requirements on realloc if memory for the new object is not allocated. It is permissible for realloc to allocate a new object, but not to allocate memory for that new object (since it's zero sized); at this point, the general escape hatch in 3.4.3 is open, since the standard imposes no requirements here, and you've got UB on a technicality. It then returns a non-null pointer, since it allocated an object, and you're in the bad place since the standard doesn't say what to do with the old object.
Now, this is clearly a drafting error and should be fixed by removing "memory" - but, AFAICT, people got angry at the idea of fixing the drafting error without also fixing the required behaviour to match their idea of the "only correct" way to define this. And rather than deal with that, the standards committee chose to simply open the escape hatch wide and say "screw you all".
I personally think this was the wrong decision, but it's the decision the committee made. And it's reflective of the current direction of travel of C - rather than make hard decisions for the benefit of users of the language (since the smaller the area covered by undefined behaviour, the easier it is to work within the language), they've chosen to punt a hard problem at the users and rely on "real programmers not making mistakes". I doubt history will be kind to the C committee over this, since it's clearly a case of "it's easier for us to do this, even if it makes life harder for language users".
Posted Jul 25, 2024 8:42 UTC (Thu)
by khim (subscriber, #9252)
[Link] (3 responses)
Objects is a “region of data storage in the execution environment”, if you don't have a storage then you can't have an object. It's unclear whether zero-sized objects are even possible in C17 (it makes it impossible to have zero-sized arrays or structs, but doesn't say if zero-sized objects are possible to get from The worst you can expect from C17 AFAICS is that That's a bit of strange situation, sure, but it's still not UB. In Rust that's perfectly normal, defined (and often used!) behavior, I don't see how and why C should be different.
Posted Jul 25, 2024 15:11 UTC (Thu)
by farnz (subscriber, #17727)
[Link] (2 responses)
C is different because the standard says that unless it explicitly defines something, that thing is UB. And in this case, by talking about memory in this one clause (something which, unlike a region of storage, is undefined), it infects the whole clause with UB if you're sufficiently motivated to find UB in a program.
If they'd not thrust that word "memory" in, this would be a full definition; but by adding an undefined term, the licence to treat the whole clause as UB is introduced.
Posted Jul 25, 2024 15:37 UTC (Thu)
by khim (subscriber, #9252)
[Link] (1 responses)
Yes, but that doesn't include terms. For unknown terms it defers to ISO/IEC 2382. Are you sure it's not defined? I suspect it's common enough term than ISO/IEC 2382, somehow. No, unknown terms like that. They may be interpreted differently, because not all combinations of ISO standard terms have meaning, but that would be a defect in the standard, it wouldn't, suddenly, lead to UB. For something to be UB it shouldn't be defined at all, not defined in a strange and/or undeciperable manner. Otherwise you may pick some term which is not defined by C standard but used extensively enough (e.g. syntax is mentioned many times, but never defined) and then claim that standard doesn't define anything at all.
Posted Jul 25, 2024 15:45 UTC (Thu)
by farnz (subscriber, #17727)
[Link]
All I can tell you is that this is the argument given by acquaintances on the committee - syntax is defined by ISO 2382, but memory is not, which is why there's wiggle-room for saying that the behaviour is undefined.
I, personally, think this is sucky, because you shouldn't be stretching to find UB whenever possible, but should be trying to reduce it to the minimum reasonable scope, but that's not current C culture.
> Changing the behavior would very likely break existing non-portable programs.
C23 reference links
C17 definition of realloc(_, 0)
> Keeping it like it was in C17 is making it undefined behaviour, just with obfuscated language to hide that from people who don't spend all their time following through the implications of standardese.
C17 definition of realloc(_, 0)
int foo(int x) {
int y = x * 2;
realloc(malloc(1), 0);
return y;
}
ret at the end). We may go from there.realloc(malloc(1), 0) as UB under C17 rules
> It is permissible for realloc to allocate a new object, but not to allocate memory for that new object (since it's zero sized)
realloc(malloc(1), 0) as UB under C17 rules
realloc), but I don't see how the definition of object as “regions of data storage in the execution environment” permits you to allocate one without also allocating memory (maybe zero bytes of memory!) for it. Sorry. No “region of data storage in the execution environment”, no object. It's as simple as that.realloc would allocate one, single, zero-sized region of storage for objects and would hand over different pointers to that same single region with all-identical bits.realloc(malloc(1), 0) as UB under C17 rules
> C is different because the standard says that unless it explicitly defines something, that thing is UB.
realloc(malloc(1), 0) as UB under C17 rules
realloc(malloc(1), 0) as UB under C17 rules
