Re: Possible GCC optimization bug
Jonathan Wakely via Gcc-help <[email protected]> Thu, 12 Feb 2026 15:22:13 +0000
| Newsgroups | gmane.comp.gcc.help |
|---|---|
| Message-ID | <CAH6eHdQG5=AC4P1qf7OtjsE7FhyNLbGbp+OemJE1hXKr54=CSw@mail.gmail.com> |
On Thu, 12 Feb 2026 at 10:27, Anubis 1101 via Gcc-help <[email protected]> wrote: > Ah, yes, I was messing with it and must've forgotten to add that back in. > Here's the corrected code: https://godbolt.org/z/E8Gsddb6G > > You're right though, that's not the bug, as it never reaches that > statement. Something that simple would've been cleaned out in one of the > other times I rewrote it. > As I already said in my first email, the bug is the undefined behaviour that UBsan reports. Compile with -fsanitize=undefined and the bug is diagnosed. > > Interestingly, when I wrote it using ternaries instead of regular if > statements, it actually shorted the length and overwrote the last character > in the string instead. If I manually increase it, it seems to behave as > normal if there is extra room in the string, but if there is only one > space, the compiler catches it as trying to write outside the string, even > though it's the correct target going by the end result. > > On Thursday, February 12th, 2026 at 2:57 AM, Jonathan Wakely < > [email protected]> wrote: > > > On Thu, 12 Feb 2026 at 01:02, Anubis 1101 via Gcc-help < > [email protected]> wrote: > > > >> I've encountered some very strange behavior in this string class I'm > working on, and I think I've narrowed it down to being a compiler bug. > >> Here's the Godbolt link: https://godbolt.org/z/axPjzP1Eq > >> All unnecessary members have been commented out, but left in for > reference. > >> > >> The basic idea is that I'm measuring the free space between the current > size of the string and the string's capacity, and then using that to > properly concatenate a single char (conditionally followed by a terminator). > >> However, the size check goes awry once it's inside an if() or switch() > check, seemingly changing to the wrong value, and then changing back. > Additionally, even if I abstract the subscript operation to the member > function (which has its own explicit bounds checking), now THAT check fails > as well, in the same way! It seems to happen most noticeably when > 'available' is zero, but because this is a single-char concatenation, it's > difficult to test it any other way (the const char* version after it has no > such issues). > >> > >> constexpr simpleString& concatenate(constchar input)noexcept{ > >> const std::size_t currentLength = length(); > >> const std::size_t available = Capacity-currentLength; > >> > >> //the bug starts happening here, in this check > >> if(available >0){ > >> std::cout <<"\n value is greater than zero. value: "<< available<< > std::endl; > >> this->operator[](currentLength)= input; //the bounds check inside this > operator ALSO exhibits the bug > >> } > >> if(available >1){ > >> std::cout <<"\n value is greater than one. value: "<< available<< > std::endl; > >> this->operator[](currentLength)='\0'; > >> } > > > > If available is 2 then you append the character, then overwrite it with > the null terminator. Should the nul be written to > operator[](currentLength+1) instead? > > > > That's not the bug though. > > > >> return*this;} > >> No amount of reformatting, code cleaning, code malformation, or > misdirection seems to unstick this bug. I tried rewriting it in different > ways, and even as a fallthrough switch statement, to no avail. Even if I > removed all instances of UB and did everything explicitly, the behavior did > not change. I've tried to isolate it by separating out the member function, > but then the bug goes away; it only seems to happen in the context of this > class. I've also never had this problem before in any other context, so I'm > not sure how to narrow it down further. I'm not experienced enough with > assembly to pinpoint exactly what's going wrong, either. > >> > >> The only thing that made any difference was dropping it to a lower > optimization level. On -O1 and -O0, it works just fine, but -O2 and -O3, it > expresses the bug. > >> Am I just missing something really simple here, or is this a legitimate > bug?