Liste des Groupes | Revenir à c arch |
On 9/4/2024 2:04 AM, David Brown wrote:No, it is not.On 03/09/2024 20:39, BGB wrote:Usually the role of the compiler is to make existing code work as it did before, not to cause it to break, even in the face of UB.On 9/2/2024 8:36 AM, MitchAlsup1 wrote:>On Mon, 2 Sep 2024 5:55:34 +0000, Thomas Koenig wrote:>
>George Neuner <gneuner2@comcast.net> schrieb:>
>I'm not going to argue about whether UB in code is wrong. The>
question I have concerns what to do with something that explicitly is
mentioned as UB in some standard N, but was not addressed in previous
standards.
>
Was it always UB? Or should it be considered ID until it became UB?
Can you give an exapmple?
Memcopy() with overlapping pointers.
I had just recently discovered that newer versions of GCC will cause code to break if it is missing a return value in C++ mode.
>
No, the error in the code caused the code to break. You don't get to blame the compiler if you write rubbish. You get to /thank/ the compiler if it has helpfully added an instruction to cause the program to stop abruptly with a UD2 instruction.
>
I would have more accepted if it turned it into a compiler error or similar though (rather than turn it into a runtime crash).The compiler /does/ generate an error - /if/ you use the compiler properly.
There has been no behaviour changes in the language or the compiler. Your code had no defined behaviour before, it has no defined behaviour now, and that is completely independent of the compiler or version.Note that in C, falling off the end of Foo here is fine - it is only if the caller attempts to use the non-existent return value that there is UB. Thus in C mode, gcc implements Foo as "ret" (when optimised), and will only warn you if you enable warnings.It worked fine in the older instance of WSL running GCC 4.8.0 ("Ubuntu 14"), but sorta exploded when switching to a newer instance of WSL (with "Ubuntu 22")...
>
In C++, it is the act of falling off the end of Foo that is UB, thus the compiler will generate an UB2 (for -O0) or no code at all (when optimised), and will warn you without requiring options.
>
But, sometimes got lazy, and did:
int InitSomething()
{
...
}
Without a return, but was an issue when it was unexpectedly crashing (and the cause was not immediately obvious, and I had not heard that there had been a behavioral change here).
Well, also partly because it is traditional to always return 'int' even when 'void' is technically more correct.Don't be absurd. That C tradition was outdated before you were born, and has never existed in C++.
But, in general, coding practices in my Verilator testbenches tends to be more lax (mostly code thrown together so the Verilog can do its thing and display its output to a window, and accept user input as needed).Finding bugs is always cheaper (in time, effort and money) the earlier you find it. Get yourself an editor or IDE that will spot such mistakes as you type them. Failing that, at least use a compiler with good warnings, use those warnings, and pay attention to them. Then learn to use the sanitizer options as the next step. It is a waste of time to wait until debugging to find such obvious and simple mistakes.
It would have been nicer if it crashed in a way where GDB could show me the point at which the crash was triggered...So:>
int Foo() { }
>
Will (in theory) cause the program to crash when called (emitting a 'UD2' instruction), except in WSL it seems this doesn't quite work correctly (the UD2 doesn't result in an immediate crash), and the program seemingly instead "goes off the rails and crashes at a later point" (GCC omits the epilog when it does this, and seemingly control flow then goes into whatever function follows in the binary, crashing when that function tries to return seemingly by branching to an invalid address or similar).
>
This was mostly effecting "init" functions in my Verilator test benches...
>
>
Well, that, and a more inconsistent variant, where if one declares struct fields as 8 and 3 bytes and then strncpy's 11 bytes into the combined field, it may also insert a UD2 and skip emitting the following code.
>
...
>
>
But, yeah, that was annoying...
>
If your compiler tells you you are doing something stupid, and you ignore it, I really don't think you can claim "the compiler broke my code".
>
as opposed to just showing "??" followed by a random address (followed by "can't read from address" or something to this effect).gcc did not break anything.
(with the "-g" option). Where, "bt" and similar didn't work either.
I could tell it wasn't crashing immediately, because if it crashed immediately it would fail at the point the UD2 occurred.
However, in a lot of cases it was carrying on and triggering a storm of debug prints for a while with often impossible values, before then crashing (in a way that looked more like a possible stack corruption).
I suspect the latter being due to some weirdness in WSL (I figured about the "UD2" mostly by trying to recreate the scenarios in "Compiler Explorer" / "godbolt.org").
Luckily stuff mostly worked after this point, as the missing return values were mostly limited to initialization functions.
Oddly though, "Compiler Explorer" was showing warnings for the missing return values, but not in GCC in WSL.
Though, have noted that generally MSVC will warn about them, and in this case I had usually fixed them, as granted it is still good practice to return a value (more so if actually used, because "random garbage" isn't usually a particularly useful return value).
But, generally, MSVC will not unexpectedly break things.
Les messages affichés proviennent d'usenet.