Indeterministic integer comparison in C/++. Have you ever noticed this bug?

Indeterministic integer comparison in C/++.
Have you ever noticed this bug?

It's All Fucked Shirt $22.14

Black Rifle Cuck Company, Conservative Humor Shirt $21.68

It's All Fucked Shirt $22.14

  1. 1 month ago
    Anonymous

    For frick's sake

  2. 1 month ago
    Anonymous
    • 1 month ago
      Anonymous

      This isn't a bug, you're just stupid.

      That's normal.

      Are you moronic? Legit question

      Why do cniles get so bitter and defensive? Why can’t they dare acknowledge a bug in their shitlang?

      • 1 month ago
        Anonymous

        What is supposed to be the bug here? The program does exactly what it is supposed to

        • 1 month ago
          Anonymous

          The fact that two equal numbers are not equal.

          • 1 month ago
            Anonymous

            >The fact that two equal numbers are not equal.

          • 1 month ago
            Anonymous

            >still no argument
            Oh no no no

          • 1 month ago
            Anonymous

            This entire thread is evidence that nobody here knows what they're talking about.

            you mean the fact they're accessing two different addresses and comparing them?

          • 1 month ago
            Anonymous

            This. It indicates a most basic misunderstanding of pointers and addresses assigned to stack variables. Fricking hell people. Think about it. It’s meant to be different addresses, until that one random blue moon running it causes coinciding random addresses for the automatically laid out memory for variables, WHICH GENERALLY NEVER HAPPENS.

            [...]
            The bug happens when you enable optimizations, OP is some kind of advanced troll
            (The bug also exists in Rust with the LLVM backend and IIRC that's where this exact code first got publicized)

            > OP is some kind of advanced troll
            This. I have to take my hat off to OP.

          • 1 month ago
            Anonymous

            >>The fact that two equal numbers are not equal.
            Ok moron. They're NOT equal the first v's address and second v's address are not the same. When you added curly braces you made the v's valid only for statements within those, however given that v might still be referenced outside those curly braces(through pointers in your example) they will remain allocated on the stack until the function returns.

      • 1 month ago
        Anonymous

        What's the use case for that code.
        The code itself is moronic, agreed and the compiler should flag it as such. But still, only a fricking idiot would write such trashy code. Is this "code" your hand?

        • 1 month ago
          Anonymous

          >the compiler should flag it as such
          genius, the compiler should also flag all code that doesn't halt

        • 1 month ago
          Anonymous

          actually, making a mistake in such a simple thing made me worried about complex codebases.

          • 1 month ago
            Anonymous

            Dont worry anon. The worst thing you can do is dive two planes into the ground uncontrollably killing 600 people.

          • 1 month ago
            Anonymous

            Good morning sir!

  3. 1 month ago
    Anonymous

    This isn't a bug, you're just stupid.

    • 1 month ago
      Anonymous

      Any arguments?

  4. 1 month ago
    Anonymous

    That's normal.

  5. 1 month ago
    Anonymous

    Are you moronic? Legit question

    • 1 month ago
      Anonymous

      Ah frick it's Hostile Henry.

      • 1 month ago
        Anonymous

        Frick off Henry.

        samegay

    • 1 month ago
      Anonymous

      Are you? Why are you getting so defensiv?

    • 1 month ago
      Anonymous

      Frick off Henry.

  6. 1 month ago
    Anonymous

    To anyone defending C or C++, I want you to know that what OP wrote is entirely representative of the level of competence I expect of you, because I see this shit all the time and I know this kind of code is actually passing code review and going into production in shit like your fricking dishwasher with its own SIM card and a screen you can tweet from

    • 1 month ago
      Anonymous

      Can also confirm, different industrial equipment though. Made me give up on the whole thing. Changing GCC string ABI alone broke so much shit it was hilarious.

      All these meme responses in disbelief but not a single technical explanation.
      Thanks but I’m sticking to Rust. C can’t compare numbers.

      Ok, here's the technical reason. You're creating two different arrays in individual scopes and taking the starting address of them. In sanity world, technically the address should be the same in both cases, but also relying on this is moronic. In OP's case, he hasn't used optimization flags so the compiler likely never bothered destructing or overwriting the old array that went out of scope.

      You forgot to enable optimizations
      Check this shit out
      https://godbolt.org/z/61daYYv6z
      140723912516952 == 140723912516952 false

      In this case, the compiler assumes you're a Black person misusing addresses to data that is already freed/unreachable so it generated code that will always make it false.

      • 1 month ago
        Anonymous

        >In this case, the compiler assumes you're a Black person misusing addresses to data that is already freed/unreachable so it generated code that will always make it false.
        wrong. look at the x86 output
        >sub rsp, 32
        >...
        >mov DWORD PTR [rbp-24], 0
        >mov DWORD PTR [rbp-20], 0
        >mov DWORD PTR [rbp-32], 0
        >mov DWORD PTR [rbp-28], 0
        >...
        >lea rax, [rbp-24]
        >mov QWORD PTR [rbp-8], rax
        >...
        >lea rax, [rbp-32]
        >mov QWORD PTR [rbp-16], rax
        >...
        >mov rax, QWORD PTR [rbp-8]
        >cmp rax, QWORD PTR [rbp-16]
        the compiler doesn't push or pop the stack for the two nested scopes. people just assumed it should

        • 1 month ago
          Anonymous

          this is the -O0 output of GCC or Clang, it isn't the optimized output where the compiler assumes your program is junk:
          e.g. -O2
          main: # @main
          push rax
          lea rdi, [rip + .L.str]
          lea rcx, [rip + .L.str.2]
          mov rsi, rsp
          mov rdx, rsp
          xor eax, eax
          call printf@PLT
          xor eax, eax
          pop rcx
          ret
          .L.str:
          .asciz "%ld == %ld 342206222 %s"

          .L.str.2:
          .asciz "false"

          I'm still correct.

          • 1 month ago
            Anonymous

            Not the person you were talking to but a compiler usually doesn't have the ability to understand issues like use-after-free (GCC and Clang don't). It just seems like it because in C and C++ this sort of thing is undefined behaviour and so the compiler sometimes optimises it out othertimes it produces code that crashes

            >Technically they do change when the optimiser changes the addresses of the variables
            That's not a change that occurs between the write and the read.
            >>If it works with volatile then it should work without volatile.
            >What do you mean?
            Volatile makes it do something at runtime that it'd otherwise do at compile time, but those two strategies should give the same result. (Unless there's UB but there isn't.)
            >I just don't know enough about LLVM to accept it's making a mistake. I usually wouldn't blame the tool because that's a bad way of thinking.
            LLVM has lots of bugs and so do all the good optimizing compilers, it's just that almost all the bugs you're likely to run into have already been found and fixed long ago. If they think it's a bug it's fair to assume it's a bug.
            >I may have to read through the LLVM issue in github to understand why the devs said it's a bug. I was hopong for a more flear example
            Pointers have weird rules but there's no reason for integers to be this unreliable.
            Does this one help?
            #include <stdio.h>
            #include <stdint.h>
            #include <stdlib.h>

            // WARNING: arg must not be 0!!!!
            void __attribute__((noinline)) dangerous_procedure(long arg) {
            printf("called dangerous_procedure() with arg = %ldn", arg);
            if (arg == 0) {
            puts("rm -rf /");
            }
            }

            int main() {
            uintptr_t a;
            uintptr_t b;
            {
            int v[2] = {0, 0};
            a = (uintptr_t) &v[0];
            }
            {
            int v[2] = {0, 0};
            b = (uintptr_t) &v[0];
            }
            long diff = a - b;
            if (diff != 0) {
            dangerous_procedure(diff);
            }
            }
            Output (clang trunk with -O):
            called dangerous_procedure() with arg = 0
            rm -rf /
            It optimized out the diff != 0 check and then passed 0 to the function anyway. That's plainly bad.

            [...]
            See above. Is this reasonable?

            >If they think it's a bug it's fair to assume it's a bug.
            I still wanna see for myself
            >Does this one help?
            I meant an LLVM ir example. I can just use clang to emit LLVM ir on this example and see what happens before and after optimisation. I think the issue is that LLVM allocates two different variables for the arrays in it's ir (can't be done otherwise) and then in some optimisation pass somehow messes up merging them

          • 1 month ago
            Anonymous

            https://godbolt.org/z/covcE7hEr

          • 1 month ago
            Anonymous

            Yeah I think that's a good example. I'm not entirely sure how lifetimes work in LLVM, I might have to look it up later but it seems the optimisation pass didn't respect the fact that due to lifetimes the arrays may have the same pointer and instead assumed they are just different pointers (which would be correct if no liftimes existed). This is definetly a bug with the optimization pass

          • 1 month ago
            Anonymous

            Hey bonus challenge:
            In C++ this is just unspecified and possibly undefined behaviour. However we established that a bug exists in LLVM and GCC behaves similarly. Is there a way to exploit the LLVM bug to cause a different bug in C++ with no undefined or unspecified behavior involved?
            Maybe not because it may require casting pointers to integers or comparing pointers directly which might be undefined behavior. Or there might be some cases in the standard where it's not undefined behavior and so we can use them?

          • 1 month ago
            Anonymous

            Someone already found this in Rust and it allows for a segfault. The soundness could probably be exploited in the same fashion from clang.
            https://github.com/rust-lang/rust/issues/107975

          • 1 month ago
            Anonymous

            Yeah but C++ shields itself from that in particular by being unspecified. Is there a way around that? You do have the LLVM bug so why wouldn't valid C++ code be able compile to something which could trigger the LLVM bug? That's the challenge

            >no you didn't.
            [...]

            [...]
            >In C++ this is just unspecified and possibly undefined behaviour.
            easy fix
            #include <stdio.h>
            #include <stdint.h>

            int main() {
            uintptr_t a;
            uintptr_t b;
            {
            int v[2] = {0, 0};
            a = (uintptr_t) (void*) &v[0];
            }
            {
            int v[2] = {0, 0};
            b = (uintptr_t) (void*) &v[0];
            }
            printf(
            "%ld == %ld %s",
            a,
            b,
            a == b ? "true" : "false"
            );
            }

            The challenge wasn't to fix it. Why does the void * cast work tho?

          • 1 month ago
            Anonymous

            >7.20.1.4 Integer types capable of holding object pointers
            >The following type designates an unsigned integer type with the property that any valid pointer
            >to void can be converted to this type, then converted back to pointer to void, and the result will
            >compare equal to the original pointer:
            >uintptr_t
            same goes for intptr_t

          • 1 month ago
            Anonymous

            So this is the correct way of casting a pointer to an integer and the programmer had created a bug. Does it work with clang? If so why is the LLVM bug not triggered in this situation?

          • 1 month ago
            Anonymous

            So this is the correct way of casting a pointer to an integer and the programmer had created a bug. Does it work with clang? If so why is the LLVM bug not triggered in this situation?

            Lol I just run it and it prints false. Given how it shouldn't according to the standard you found the C++ bug both in Clang and GCC. I thought you were trying to fix the program lol

    • 1 month ago
      Anonymous

      That's on the moronic programmers, not the language you deranged troon.

  7. 1 month ago
    Anonymous

    Ah frick Henry got to you first, I'll explain it to you. Sorry about him.

    uintptr_t is an unsigned variable, so this variable can be overwritten by other components of your program, because your program doesn't know how to identify whether or not the space is being used.

    • 1 month ago
      Anonymous

      No that's not why, you incompetent gay.

      • 1 month ago
        Anonymous

        https://en.wikipedia.org/wiki/Digital_signature
        dumbfrick

        • 1 month ago
          Anonymous

          This isn't even tangentially related.

          • 1 month ago
            Anonymous

            >signed integer
            >unsigned integer
            do you already realize how stupid you are or should I keep going?

          • 1 month ago
            Anonymous

            >talks about integers
            >links article on cryptography

          • 1 month ago
            Anonymous

            https://stackoverflow.com/questions/8225510
            >In cryptography "signed" can also mean "has a digital signature". Unsigned would then be "doesn't have a digital signature".

          • 1 month ago
            Anonymous

            Yes, and we are talking about uintptr_t, which is an unsigned integer.
            Cryptography has nothing to do with this thread at all.

          • 1 month ago
            Anonymous

            >feeding the troll
            Shaking my head, onii-chan.

  8. 1 month ago
    Anonymous

    All these meme responses in disbelief but not a single technical explanation.
    Thanks but I’m sticking to Rust. C can’t compare numbers.

    • 1 month ago
      Anonymous

      OP made 2 different pointers and compared them. I might be autistic but I can't tell if OP is pretending to be moronic and everyone is playing along or if everyone is actually moronic.

      • 1 month ago
        Anonymous

        >OP made 2 different pointers and compared them
        wrong
        read the thread, dumb moron

      • 1 month ago
        Anonymous

        Start at the post right after that:

        You forgot to enable optimizations
        Check this shit out
        https://godbolt.org/z/61daYYv6z
        140723912516952 == 140723912516952 false

  9. 1 month ago
    Anonymous

    You forgot to enable optimizations
    Check this shit out
    https://godbolt.org/z/61daYYv6z
    140723912516952 == 140723912516952 false

    • 1 month ago
      Anonymous

      what in the goddamn

    • 1 month ago
      Anonymous

      so whats happening there if b is unused its address is discarded if using -O?

    • 1 month ago
      Anonymous

      if it's a llvm bug, why does is its also present in gcc?

      • 1 month ago
        Anonymous

        This bug originally was found in rustc. Then people realized it also affects clang. And then it also was found in GCC.

        It's really weird stuff. Probably some common form of optimization.

        >why they haven't fixed it yet.
        Probably because you have to do some really moronic stuff to make it happen.

        It's still a bug in a compiler. If it was an UB in context of languages it wouldn't be a problem, but this should never happen in C or Rust.

      • 1 month ago
        Anonymous

        There are subtle variations between the bug in gcc and llvm. For example, the snippet in

        They're converted to integers before they go out of scope. And naively you'd expect dangling pointers to only be invalid to dereference.
        In Rust you write basically the same thing.

        [...]
        The first array goes out of scope before the lifetime of the second array begins, so it can reuse the memory.
        The pointers point to two different allocations so the optimizer treats them as unequal even though they happen to have the same address. (Even if you cast them to integers first.) But the hardware just goes by address and considers them equal.
        So if you can get one comparison to be evaluated by the compiler and another by the hardware you get an inconsistency.

        [...]
        >It is the compiler technically optimizing wrongly, by assuming that a and b point to different addresses
        It actually is allowed to do this up to a point. I don't remember if it's technically valid to take it this far but the standard defines pointers very abstractly.
        The reason optimizations like these are useful is that you want to know whether anyone else might be looking at a value. If you know that a value can't be unexpectedly mutated through some far-off pointer then you can perform a lot more optimizations. But if it were possible to guess a variable's address then that goes out of the window, you can never be sure that some other code didn't manage to guess a pointer and mutate the value anyway.

        [...]
        [...]
        You just have to jiggle it a bit.
        #include <stdio.h>
        #include <stdint.h>

        int *get_ptr() {
        int v[2] = {0, 0};
        return &v[0];
        }

        int main() {
        int* a = get_ptr();
        int* b = get_ptr();
        printf(
        "%p == %p evaluates to %sn",
        a,
        b,
        a == b ? "true" : "false"
        );
        }
        0x7fffa6f8b4d0 == 0x7fffa6f8b4d0 evaluates to false
        This one works with both int * and uintptr_t.

        breaks in clang with -O, but never in GCC.

    • 1 month ago
      Anonymous

      Neat, also OP is a homosexual.

    • 1 month ago
      Anonymous

      i've heard this is the type if issue that only appears if you set your compiler settings to be so aggressive when optimizing that it basically breaks your code

    • 1 month ago
      Anonymous

      I don't get it. You're creating a temporary and stashing its address, then letting the temporary go out of scope. How is this different from returning the address of a local from a function? To me this seems like the same kind of all-bets-are-off UB.

      • 1 month ago
        Anonymous

        read the thread, dumb moron

        • 1 month ago
          Anonymous

          aren't you tired by now?

          • 1 month ago
            Anonymous

            no

            I think I will just not write shitcode anon.

            you won't write any code because you are a dumb LARPer

          • 1 month ago
            Anonymous

            >no
            I think you need to find a better hobby.

        • 1 month ago
          Anonymous

          I think I will just not write shitcode anon.

      • 1 month ago
        Anonymous

        it is, but the concern and the optimizer "bug" is more the fact they're turning the address into an integer that they should be able to have clear semantics with, whether the semantics are meaningful is another thing. I'm too lazy to language lawyer C/C++ shit to care and I agree this is a pretty Black personlicious problem to have, but it even causes unsoundness in Rust, which is probably the best statically analyzed user of LLVM, so it might be a bigger issue.

        • 1 month ago
          Anonymous

          >so it might be a bigger issue
          it is, and nobody is working on fixing it after it turned out to be too hard to fix.
          https://github.com/rust-lang/rust/issues/107975#issuecomment-1439817961

          • 1 month ago
            Anonymous

            I can think of a solution if LLVM does not fix the bug but it's somewhat nasty. Basically treat nested scopes as closures that capture the whole environment and are executed right after their declaration. Actually it's not that nasy now that I think about it lol. This will effectively push a scope to the stack (based on whatvwas discussed earlier in the thread) and this issue would be circumvented. Unless closures do not have their own stack frame. In that case this won't work and it gets nasty. Also it might reduce possible optimizations from within the block to the outside

          • 1 month ago
            Anonymous

            This can happen with separate stack frames too, see

            They're converted to integers before they go out of scope. And naively you'd expect dangling pointers to only be invalid to dereference.
            In Rust you write basically the same thing.

            [...]
            The first array goes out of scope before the lifetime of the second array begins, so it can reuse the memory.
            The pointers point to two different allocations so the optimizer treats them as unequal even though they happen to have the same address. (Even if you cast them to integers first.) But the hardware just goes by address and considers them equal.
            So if you can get one comparison to be evaluated by the compiler and another by the hardware you get an inconsistency.

            [...]
            >It is the compiler technically optimizing wrongly, by assuming that a and b point to different addresses
            It actually is allowed to do this up to a point. I don't remember if it's technically valid to take it this far but the standard defines pointers very abstractly.
            The reason optimizations like these are useful is that you want to know whether anyone else might be looking at a value. If you know that a value can't be unexpectedly mutated through some far-off pointer then you can perform a lot more optimizations. But if it were possible to guess a variable's address then that goes out of the window, you can never be sure that some other code didn't manage to guess a pointer and mutate the value anyway.

            [...]
            [...]
            You just have to jiggle it a bit.
            #include <stdio.h>
            #include <stdint.h>

            int *get_ptr() {
            int v[2] = {0, 0};
            return &v[0];
            }

            int main() {
            int* a = get_ptr();
            int* b = get_ptr();
            printf(
            "%p == %p evaluates to %sn",
            a,
            b,
            a == b ? "true" : "false"
            );
            }
            0x7fffa6f8b4d0 == 0x7fffa6f8b4d0 evaluates to false
            This one works with both int * and uintptr_t.

            .

          • 1 month ago
            Anonymous

            Oh I hadn't noticed that. But how? Does it happen to be able to evaluate the pointer at compile time? Probably not because it should be the same. Does it just assume pointers to different local variables point to different things? But how does it know the pointer retunred by the function is a pointer to a local thing?

          • 1 month ago
            Anonymous

            Oh I hadn't noticed that. But how? Does it happen to be able to evaluate the pointer at compile time? Probably not because it should be the same. Does it just assume pointers to different local variables point to different things? But how does it know the pointer retunred by the function is a pointer to a local thing?

            Wait LLVM doesn't use a stack so maybe it just assumes that stack frames just exist and each one is in a unique address which makes sense in the LLVM ir so if that's the case it wouldn't be a bug in LLVM, right? Unless LLVM lifetimes get in the way again and it turns out it is a bug

          • 1 month ago
            Anonymous

            >it wouldn't be a bug in LLVM
            wrong
            https://github.com/llvm/llvm-project/issues/45725

          • 1 month ago
            Anonymous

            Oh I hadn't noticed this was literally that example lol. What I was saying was this would be correct if lifetimes didn't exist.
            So basically whoever implemented lifetimes in LLVM just made them comments lol

          • 1 month ago
            Anonymous

            i've never tried looking at anything language-design related, but is it really that hard to just check
            >compare pointer to other pointer? actually perform comparison instead of optimizing it to false
            i decompiled a sample program using IDA to confirm and yeah, in release mode it straight up doesn't even contain the "true" string nor perform the comparison, just passes the "false" string straight to printf

          • 1 month ago
            Anonymous

            >is it really that hard
            yes
            https://www.ralfj.de/blog/2020/12/14/provenance.html

  10. 1 month ago
    Anonymous

    Henry here, yes the actual problems is that when you put a uintptr_t in brackets the program does something magical and always adds that giant number to your program

  11. 1 month ago
    Anonymous

    >two separate variables are given separate addresses
    And? Where's the bug?

  12. 1 month ago
    Anonymous

    This entire thread is evidence that nobody here knows what they're talking about.

  13. 1 month ago
    Anonymous

    Remove your parenthesis. {
    }
    The code inside this scope is not being executed.

  14. 1 month ago
    Anonymous

    >xxx1736 = xxx1728 evaluates to false
    where is the issue there? last time I checked 1736 != 1728, unless they changed something big in C23

    • 1 month ago
      Anonymous

      I see a lot of replies calling cniles hostile, but not a single explanation of what the bug is supposed to be.
      a == 140721512071736
      b == 140721512071728
      Therefore a == b evaluates to false. What is the issue exactly?

      The bug happens when you enable optimizations, OP is some kind of advanced troll
      (The bug also exists in Rust with the LLVM backend and IIRC that's where this exact code first got publicized)

      • 1 month ago
        Anonymous

        Huh, that's strange.

        • 1 month ago
          Anonymous

          Its not really strange; compiler writers are gods. The second array (if not both) is/are probably being optimized away, but the static analysis of the program established a != b and this was recorded as a constant in the inequality comparison.

          I didn't look at godbolt assembly, just a guess.

          • 1 month ago
            Anonymous

            Yeah, I get it now.
            This is all pretty inconsequential though since you have to write bad dumb code to end up in a situation like this.

      • 1 month ago
        Anonymous

        C bros…. Not like this…..

        • 1 month ago
          Anonymous

          >llvm bug
          >was reported as a bug in rust since it was first discovered there
          >C bros not like this
          >posts söyjaks of c++ programmers, not c programmers

      • 1 month ago
        Anonymous

        It’s joever

      • 1 month ago
        Anonymous

        nice. seems like a legit bug, but it's interesting that it seems to appear in all major C++ compilers. I wonder if it's because of similar tricks in the implementation or if the language itself is underspecified.

      • 1 month ago
        Anonymous

        >The result of the integer cast is unspecified
        wrong
        >6.3.2.3p5
        >An integer may be converted to any pointer type. Except as previously specified, the result is imple-
        >mentation-defined, might not be correctly aligned, might not point to an entity of the referenced
        >type, and might be a trap representation.68

        frick
        >6.3.2.3p6
        >Any pointer type may be converted to an integer type. Except as previously specified, the result
        >is implementation-defined. If the result cannot be represented in the integer type, the behavior is
        >undefined. The result need not be in the range of values of any integer type

        It's a good thing I would never consider casting a pointer to an integer, because it's scary.

        • 1 month ago
          Anonymous

          I cast pointers to integers, and then back to pointers, all the time. It's one of the easiest ways to implement a dynamic array of arbitrary type.

          • 1 month ago
            Anonymous

            Why not use void pointers?

          • 1 month ago
            Anonymous

            why do you need integers for that? isn't void* enough?

            I do use void pointers.
            You cannot do pointer arithmetic on void pointers because void does not have a specified size. Trying to get an offset address from a void* by simply adding sizeof(type) * index doesn't work because that's basically a void* dereference. So, cast to uintptr_t, add the offset, and cast back.

          • 1 month ago
            Anonymous

            why not ((type*)v)[index]?

          • 1 month ago
            Anonymous

            That would require being able to pass a type to a function. C does not support this and I do not like function-like macros.

          • 1 month ago
            Anonymous

            To clarify, my dynamic arrays are similar to vectors in C++. They have insert, remove, push, and pop functions. The size of the type is stored with the array to make all of this possible.

          • 1 month ago
            Anonymous

            then why not (char*)v+(index*sizeof(type))?

          • 1 month ago
            Anonymous

            I certainly could have done it that way, but didn't. I have no explanation for this. Still requires a cast either way.

            [...] and 6127022736 are two different memory addresses
            ??

            I think you replied to the wrong guy.

          • 1 month ago
            Anonymous

            [...]

            and 6127022736 are two different memory addresses
            ??

          • 1 month ago
            Anonymous

            meant for

            you get exactly what is expected on C, two different variables occupying two different memory addresses.
            why do you expect something else?

          • 1 month ago
            Anonymous

            why do you need integers for that? isn't void* enough?

        • 1 month ago
          Anonymous

          NTA but I had to personally because of a Rust oddity.
          Raw pointers are not Send in Rust for some reason. Meaning you can't just move a raw pointer into another thread, I had to cast it to usize and back. Why is that a thing? I'm not sure. I asked about it on their official IRC and it caused quite a discussion among people. The general consensus was that Send is opt-in and no one made raw pointers Send and that's it.
          It was long time ago, so maybe it got changed or maybe there is some justification for that(provenance?). It could be interesting to make a GitHub issue about that I guess.

          • 1 month ago
            Anonymous

            https://doc.rust-lang.org/nomicon/send-and-sync.html
            >Most uses of raw pointers should be encapsulated behind a sufficient abstraction that Send and Sync can be derived. For instance all of Rust's standard collections are Send and Sync (when they contain Send and Sync types) in spite of their pervasive use of raw pointers to manage allocations and complex ownership. Similarly, most iterators into these collections are Send and Sync because they largely behave like an & or &mut into the collection.

          • 1 month ago
            Anonymous

            Oh interesting.
            AFAIR I was doing some low level stuff with mapping GPU memory to virtual memory and that's where I got that issue.
            I was not that experienced in Rust back then so there probably was some nicer abstraction possible than sending raw pointers themselves.

          • 1 month ago
            Anonymous

            Adding onto

            https://doc.rust-lang.org/nomicon/send-and-sync.html
            >Most uses of raw pointers should be encapsulated behind a sufficient abstraction that Send and Sync can be derived. For instance all of Rust's standard collections are Send and Sync (when they contain Send and Sync types) in spite of their pervasive use of raw pointers to manage allocations and complex ownership. Similarly, most iterators into these collections are Send and Sync because they largely behave like an & or &mut into the collection.

            , I think you're supposed to store them in a struct and manually declare that the struct is Send/Sync. There's something similar with UnsafeCell, which isn't Sync either. Bit annoying if you're not building an abstraction though.
            I had to opt out of Send/Sync once and I think I did it by adding a PhantomData<Rc<()>> member. Very ugly and unintuitive, it does make sense that they favor opt-in over opt-out.

            >You don't need a specification to determine that two integers with equal values should be equal.
            If you are being reasonable that is. Technically one could define a language in which 1 + 1 evaluates to 3. Also the docs are good enough to justify that it is a bug until a formal specification is created
            [...]
            According to [...] converting pointers to integers is unspecified in C++ (likely also in C) as rhe other poster was correctly claiming. According to it's a bug in rustc. I'm very inteterested in seeing how LLVM deals with it. I don't know much about LLVM but it seems to me that it shouldn't be a bug because LLVM gives you seperate pointers for each variable (even the local ones). However there may be a bug when LLVM puts the variables in the same address during an optimization pass and then maybe forgets to set the value pointers equal? But how would that even happen? Have they reproduced the bug in LLVM ir?

            It's implementation-defined, so it doesn't give you permission to emit fricked-up evil integers. You can't predict which integers you get but once you have the integers they should be well-behaved. Unless you can do a weird reading based on trap representations but that's now what these compilers are going for anyway, they want to let you access the actual address as an integer.
            It's a bug in rustc insofar as you can run into this bug when you use rustc. It's not actually a bug in rustc's own code, it's a LLVM bug.

            gcc trunk (14+?) looks fine now
            https://godbolt.org/z/rbePhz586

            #include <stdio.h>
            #include <stdint.h>

            int main() {
            volatile int i = 0;
            uintptr_t a;
            uintptr_t b;
            {
            int v[2] = {0, 0};
            a = (uintptr_t) &v[i];
            }
            {
            int v[2] = {0, 0};
            b = (uintptr_t) &v[i];
            }
            printf(
            "%ld == %ld %s",
            a,
            b,
            a == b ? "true" : "false"
            );
            }

            Huh, and with v[2] it correctly says "true". They must have fixed something recently. I don't yet trust that they completely fixed it but I tried a few things and can't make it slip up.

      • 1 month ago
        Anonymous

        This is more like the opposite of a bug. Think about it- those are two different variables, and should never evaluate as equal to one another assuming that the program is executed as printed.

        The optimizer throws a wrench into this plan, by optimizing the two variables to occupy the same block of memory. (which happens, by the way, because those addresses are never written to).

        So two variables that should evaluate as different may evaluate as the same, which is bad!

        But they don't!!!

        Because the compiler performs a static analysis and determines that a == b should always, under all circumstances, return false- regardless of what the address values actually are.

        • 1 month ago
          Anonymous

          >dumb and moronic LARPs as a compiler developer
          >is wrong
          dumb moron

          • 1 month ago
            Anonymous

            he's right dipshit. use Godbolt yourself and compare -O0 with even -O1 with clang or gcc.
            both basically throw the program away when -O is passed.

          • 1 month ago
            Anonymous

            he is wrong, dumb moron. the two integers have the same value, so a == b should be true.
            It's either a compiler bug, or there is some UB frickery going on.
            In the case of LLVM, it has been confirmed as a bug.

          • 1 month ago
            Anonymous

            They're only the same value because of UB. You're fatally assuming pointers are integers which is what the dumbest gorilla Black folk do.

          • 1 month ago
            Anonymous

            >You're fatally assuming pointers are integers
            You are fatally unable to read, the pointers are cast to integers.

    • 1 month ago
      Anonymous

      There is no issue, OP probably copied this code from some stackoverflow page but forgot to set optimizations to get the bug at

      You forgot to enable optimizations
      Check this shit out
      https://godbolt.org/z/61daYYv6z
      140723912516952 == 140723912516952 false

      , then was too moronic to check their screencap before posting & spending the next 30 mins of their life screaming cniles at everyone
      Just your average IQfy cniles poster

      • 1 month ago
        Anonymous

        It originally comes from this comment on Rust's issue tracker: https://github.com/rust-lang/rust/issues/107975#issuecomment-1430429347
        I think it's some sort of double/triple false-flag

        • 1 month ago
          Anonymous

          Let me spoil a secret for you:
          All language wars on IQfy are trolls trolling trolls.

          • 1 month ago
            Anonymous

            Not me, I'm painfully sincere
            1/3 of the time I even get to have a productive conversation

            I'm not an expert at C and I honestly have no clue what's supposed to happen or not what's supposed to happen?

            What exactly is happening here? I didn't get the same results?

            It should be (uintptr_t) &v[0], it's the unary & and not the binary &. To see something actually interesting you also need to build with optimizations, and I'm not sure it happens on MSVC (let me know though, I've seen claims that MSVC doesn't do any crazy optimizations).

        • 1 month ago
          Anonymous

          Yeah I wouldn't be surprised, these language troll threads are pretty homosexual, I'm going back to the new Car() thread

  15. 1 month ago
    Anonymous

    I see a lot of replies calling cniles hostile, but not a single explanation of what the bug is supposed to be.
    a == 140721512071736
    b == 140721512071728
    Therefore a == b evaluates to false. What is the issue exactly?

  16. 1 month ago
    Anonymous

    I don't get this problem actually, must be the CIA.

  17. 1 month ago
    Anonymous

    We must consult Hostile Henry.

    Henry what is the problem?

  18. 1 month ago
    Anonymous

    I'm not an expert at C and I honestly have no clue what's supposed to happen or not what's supposed to happen?

    What exactly is happening here? I didn't get the same results?

    • 1 month ago
      Anonymous

      Which compiler are you using?
      I just tested it in mingw-w64 and got the same bug mentioned throughout the thread, but you seem to be getting correct behavior.

      • 1 month ago
        Anonymous

        The oldest C compiler I could find
        web.archive.org/web/20190901000000*/http://pcc.ludd.ltu.se/ftp/pub/win32/

        https://web.archive.org/web/20191019051303/http://pcc.ludd.ltu.se/ftp/pub/win32/

      • 1 month ago
        Anonymous

        Compile command is
        pcc -o outputname.exe inputname.c

        • 1 month ago
          Anonymous

          Yeah, as previously stated, you have to enable optimizations for the bug to occur.
          -O0 results in different addresses, so the false evaluation makes sense.
          -O1 through -O3 all result in the same address for both variables, but you still get a false evaluation.
          Also, like

          Not me, I'm painfully sincere
          1/3 of the time I even get to have a productive conversation

          [...]
          It should be (uintptr_t) &v[0], it's the unary & and not the binary &. To see something actually interesting you also need to build with optimizations, and I'm not sure it happens on MSVC (let me know though, I've seen claims that MSVC doesn't do any crazy optimizations).

          pointed out, you're always getting zero because you're anding the address with whatever is already in a and b instead of just assigning the address to them.

    • 1 month ago
      Anonymous

      >a = (uintptr_t) a & v[0];
      >b = (uintptr_t) b & v[0];
      anon...

  19. 1 month ago
    Anonymous

    The "v" array in the two code blocks is not the same array, which means it doesn't necessarily have the same address.
    If you do this again but declare the "v" array at the top of the function, there won't be a problem.

    • 1 month ago
      Anonymous

      This is the actual bug that OP was too moronic to verify that he was reproducing:

      You forgot to enable optimizations
      Check this shit out
      https://godbolt.org/z/61daYYv6z
      140723912516952 == 140723912516952 false

      [...]
      The bug happens when you enable optimizations, OP is some kind of advanced troll
      (The bug also exists in Rust with the LLVM backend and IIRC that's where this exact code first got publicized)

      which occurs when the v in the two code blocks ARE optimized to the same array, but the compiler forgets about it and incorrectly optimizes a == b.

  20. 1 month ago
    Anonymous

    >Indeterministic integer comparison in C/++.
    It's a pointer comparison, I suppose you'd get the correct result casting the pointers to an integer first, because there are special things in place for pointer comparison in the compiler, IINM.

    homosexual.

    • 1 month ago
      Anonymous

      >I suppose you'd get the correct result casting the pointers to an integer first
      No, it propagates the pointer bullshit to casted integers. uintptr_t is an integer type, typedef'd to unsigned long int on my system
      OP doesn't show the problem though, see

      [...]
      The bug happens when you enable optimizations, OP is some kind of advanced troll
      (The bug also exists in Rust with the LLVM backend and IIRC that's where this exact code first got publicized)

      • 1 month ago
        Anonymous

        >uintptr_t is an integer type
        You're right. I never use these, so whatever.
        >OP doesn't show the problem though
        Yes, OP sucks wieners, but the issue does exist.
        It seems to be a compiler optimization bug, wherein it assumes at compile time that a != b, but ignores that a == b is not impossible.
        It's not strictly correct, but the code is a bullshit example anyways, have a and b be passed as args to the program and it cannot optimize that away and should then evaluate correctly.

  21. 1 month ago
    Anonymous

    I can see why this wasn't found for a long time, it's a weird and useless thing to do. Basically an inert bug.

  22. 1 month ago
    Anonymous

    Guys why is it a bug tho? They are pointers to variables that have been put out of scope. Using these pointers is incorrect in the first place. Why should they be equal? Especially since they point to different variables in different scopes?
    Interested in the Rust version of the bug where it makes sense? If so it would be a Rust implementation bug

    • 1 month ago
      Anonymous

      The bug is in an LLVM optimization pass
      Please read

      • 1 month ago
        Anonymous

        Can't you just make it a 10 sec tiktok? I'm a zoomer so I can't focus on text

        >Using these pointers is incorrect in the first place
        No, it is not, you are "caching" the memory addresses as unsigned integers and then performing an equality comparison.
        It is the compiler technically optimizing wrongly, by assuming that a and b point to different addresses, even if in practice they aren't.

        >"caching" the memory addresses as unsigned integers
        No because the types of a and b are pointers to unsigned integers if I understand correctly so you did not store two integers. Also even if you did save them as integers:

        The pointers ARE equal (OP pic unrelated), but the compiler incorrectly assumes that they aren't.
        >Interested in the Rust version of the bug where it makes sense? If so it would be a Rust implementation bug
        It's the same bug. It happens in Rust because Rust uses LLVM. Don't ask me how GCC independently acquired this bug.

        >The pointers ARE equal
        I'm not convinced. Does the languahe specification say that pointers to variables that are out of scope can be equal or is it undefined behavior?
        >Don't ask me how GCC independently acquired this bug.
        I suspect because it's probably undefined behavior, likely for both C++ and LLVM

        They're converted to integers before they go out of scope. And naively you'd expect dangling pointers to only be invalid to dereference.
        In Rust you write basically the same thing.

        [...]
        The first array goes out of scope before the lifetime of the second array begins, so it can reuse the memory.
        The pointers point to two different allocations so the optimizer treats them as unequal even though they happen to have the same address. (Even if you cast them to integers first.) But the hardware just goes by address and considers them equal.
        So if you can get one comparison to be evaluated by the compiler and another by the hardware you get an inconsistency.

        [...]
        >It is the compiler technically optimizing wrongly, by assuming that a and b point to different addresses
        It actually is allowed to do this up to a point. I don't remember if it's technically valid to take it this far but the standard defines pointers very abstractly.
        The reason optimizations like these are useful is that you want to know whether anyone else might be looking at a value. If you know that a value can't be unexpectedly mutated through some far-off pointer then you can perform a lot more optimizations. But if it were possible to guess a variable's address then that goes out of the window, you can never be sure that some other code didn't manage to guess a pointer and mutate the value anyway.

        [...]
        [...]
        You just have to jiggle it a bit.
        #include <stdio.h>
        #include <stdint.h>

        int *get_ptr() {
        int v[2] = {0, 0};
        return &v[0];
        }

        int main() {
        int* a = get_ptr();
        int* b = get_ptr();
        printf(
        "%p == %p evaluates to %sn",
        a,
        b,
        a == b ? "true" : "false"
        );
        }
        0x7fffa6f8b4d0 == 0x7fffa6f8b4d0 evaluates to false
        This one works with both int * and uintptr_t.

        >They're converted to integers before they go out of scope. And naively you'd expect dangling pointers to only be invalid to dereference.
        Does the C++ specification say any of these statements?

        • 1 month ago
          Anonymous

          a and b are uintptr_t, which is an integer type of the same size as a pointer. They aren't pointers, they are integers.

          • 1 month ago
            Anonymous

            I see. So the questions now are if pointers in this example can be equal and if casting unequal pointers to integers can produce equal integers

            I did it on clang with -O like [...], I guess it's pretty fragile.
            clang also has the warning, but even with that warning this is unexpected.

            [...]
            >Does the C++ specification say any of these statements?
            The first statement is just a factual description of how the code is written. It performs the cast before the end of the lifetime.
            The second statement includes the word "naively" for a reason. There's an astonishing number of things that are invalid to do even with live pointers.

            [...]
            They often independently invent the same bugs.

            >The first statement is just a factual description of how the code is written.
            Yes I did not know about the uintptr_t type sorry

            I did it on clang with -O like [...], I guess it's pretty fragile.
            clang also has the warning, but even with that warning this is unexpected.

            [...]
            >Does the C++ specification say any of these statements?
            The first statement is just a factual description of how the code is written. It performs the cast before the end of the lifetime.
            The second statement includes the word "naively" for a reason. There's an astonishing number of things that are invalid to do even with live pointers.

            [...]
            They often independently invent the same bugs.

            >The second statement includes the word "naively" for a reason.
            So it may be a bug on the part of the programmer not the compiler, right?

            >Does the languahe specification say that pointers to variables that are out of scope can be equal or is it undefined behavior?
            Afaik the result is unspecified, but not undefined, since pointers are just numbers.

            I can't find the standard or I'd look into it

            I should add that the Rust counterpart is definitely a bug. Idk what the C++ standard says about treating pointers like numbers, but Rust absolutely does treat raw pointers as numbers (as long you don't do anything unsafe{} with it.)

            Rust doesn't have a specification I think so I guess we can't answer. LLVM tho I think assumes all variables are stored in a different address regardless so if that's the case that's what Rust does

          • 1 month ago
            Anonymous

            >Rust doesn't have a specification I think so I guess we can't answer.
            You don't need a specification to determine that two integers with equal values should be equal.

          • 1 month ago
            Anonymous

            You need a specification to determine if it's a compiler bug or not. But also if there is no specification Rust doesn't really support what you said, however logical it may be. I've also heard the phrase "the compiler is the specification" being thrown around so yeah

            >if casting unequal pointers to integers can produce equal integers
            Are you actually moronic?

            Unequal in the sense that they are pointing to different variables which hold the same address in memory. I'm not sure what the standard says about that but a simple example which is similar to what is happening here would be calling a function and returning a pointer to one of it's local variables then passing it to another function which compares that pointer with a pointer to one of it's own local variables which happens to be in the same address. That surely has to be one of two things: undefined behavior or the pointers being unequal, unless the standard says something else. Idk about provenance that the other poster says but I might look into it since it might be a better way to explain this concept

            Try this one:
            #include <stdio.h>
            #include <stdint.h>

            int main(){
            int* a;
            int* b;
            {
            int v[2] = {0, 0};
            a = &v[0] + 2;
            }
            {
            int v[2] = {0, 0};
            b = &v[0];
            }
            printf(
            "%p == %p evaluates to %sn",
            a,
            b,
            a == b ? "true" : "false"
            );
            }

            [...]
            They're working on strict provenance to explicitly make them more than just numbers.

            [...]
            >So it may be a bug on the part of the programmer not the compiler, right?
            I'm not sure but I think this might still be a compiler bug. If this is a bug on the part of the programmer then I don't know where the UB is supposed to be introduced. Is it when you cast the pointers to integers? Or do integers carry along secret provenance information?

            >UB is supposed to be introduced
            In my opinion it should be because the addresses of two variables who belong to different scopes should not be comparable. But this is just my opinion based on what I think is logical, I don't know what the standard says

          • 1 month ago
            Anonymous

            >You need a specification to determine if it's a compiler bug or not.
            You don't need a specification to determine that two integers with equal values should be equal.

          • 1 month ago
            Anonymous

            >the addresses of two variables who belong to different scopes should not be comparable
            That's fair game if the addresses are stored in pointers but if they're stored in integers it gets very weird. Now there exists a special dangerous kind of integer value.

          • 1 month ago
            Anonymous

            >if casting unequal pointers to integers can produce equal integers
            Are you actually moronic?

          • 1 month ago
            Anonymous

            no, you are moronic. pointers have provenance, integers don't.

          • 1 month ago
            Anonymous

            Casting a pointer to an integer of the same size in C literally just results in that pointer's bytes being perfectly copied to the integer.
            So casting unequal pointers to integers will always result in unequal integers.
            You are moronic if you try to argue otherwise.

          • 1 month ago
            Anonymous

            wrong, pointers with equal address can compare inequal if they have different provenance.
            casting a pointer to an integer gives you the address of the pointer and throws away the provenance.
            https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2363.pdf

          • 1 month ago
            Anonymous

            My apologies. I usually avoid having multiple pointers pointing to the same address so this sort of thing has never been a concern for me. Thank you for the link.

        • 1 month ago
          Anonymous

          >Does the languahe specification say that pointers to variables that are out of scope can be equal or is it undefined behavior?
          Afaik the result is unspecified, but not undefined, since pointers are just numbers.

          • 1 month ago
            Anonymous

            >since pointers are just numbers
            wrong, pointers have provenance.

          • 1 month ago
            Anonymous

            Does provenance apply even if you don't dereference?

            I see. So the questions now are if pointers in this example can be equal and if casting unequal pointers to integers can produce equal integers
            [...]
            >The first statement is just a factual description of how the code is written.
            Yes I did not know about the uintptr_t type sorry
            [...]
            >The second statement includes the word "naively" for a reason.
            So it may be a bug on the part of the programmer not the compiler, right?
            [...]
            I can't find the standard or I'd look into it
            [...]
            Rust doesn't have a specification I think so I guess we can't answer. LLVM tho I think assumes all variables are stored in a different address regardless so if that's the case that's what Rust does

            The rust docs explicitly state that there's supposed to be no UB if you don't use unsafe.

          • 1 month ago
            Anonymous

            >Does provenance apply even if you don't dereference?
            Don't quote me on this but IIRC it's UB to even do a < b if a and b are pointers with different provenance and this came up in CPython

            Casting a pointer to an integer of the same size in C literally just results in that pointer's bytes being perfectly copied to the integer.
            So casting unequal pointers to integers will always result in unequal integers.
            You are moronic if you try to argue otherwise.

            What do you consider "unequal pointers"? Pointers that have different addresses? Pointers that compare unequal? Pointers that point to different objects?

          • 1 month ago
            Anonymous

            >IIRC it's UB to even do a < b if a and b are pointers with different provenance
            Interesting. Wouldn't that mean glibc's implementation of memmove is technically UB, at least under some circumstances, since it effectively compares its pointers (after casting them to unsigned integers?)
            rettype
            inhibit_loop_to_libcall
            MEMMOVE (a1const void *a1, a2const void *a2, size_t len)
            {
            unsigned long int dstp = (long int) dest;
            unsigned long int srcp = (long int) src;

            /* This test makes the forward copying code be used whenever possible.
            Reduces the working set. */
            if (dstp - srcp >= len) /* *Unsigned* compare! */
            {
            /* Copy from the beginning to the end. (SNIP) */
            }
            else
            {
            /* Copy from the end to the beginning. (SNIP) */
            }
            RETURN (dest);
            }

          • 1 month ago
            Anonymous

            >after casting them to unsigned integers

          • 1 month ago
            Anonymous

            Found the bit I was thinking of. N3096 6.5.8.6:
            >When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.
            And for that code, 6.5.6.10:
            >When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object
            My guess is that the integer cast makes it OK. If these were pointers then it'd definitely be invalid by the letter of the standard.
            So that's one point for this being an actual compiler bug (which is also how the LLVM people are treating it).

          • 1 month ago
            Anonymous

            The result of the integer cast is unspecified, so whether the result of the integer arithmetic and comparison actually means anything depends on the compiler. In theory, two intptr_t could be equal but convert back to different pointers, or two intptr_t converted from the same pointer could be unequal.
            Of course glibc only claims to be compatible with GCC, so they can do whatever they want as long as that much works.

          • 1 month ago
            Anonymous

            >two intptr_t converted from the same pointer could be unequal
            I have trouble believing this

          • 1 month ago
            Anonymous

            Correct me if I'm wrong, but a pointer should always be equal to itself, so two intptr_t variables cast from the same pointer should be identical.

          • 1 month ago
            Anonymous

            >The result of the integer cast is unspecified
            wrong
            >6.3.2.3p5
            >An integer may be converted to any pointer type. Except as previously specified, the result is imple-
            >mentation-defined, might not be correctly aligned, might not point to an entity of the referenced
            >type, and might be a trap representation.68

          • 1 month ago
            Anonymous

            frick
            >6.3.2.3p6
            >Any pointer type may be converted to an integer type. Except as previously specified, the result
            >is implementation-defined. If the result cannot be represented in the integer type, the behavior is
            >undefined. The result need not be in the range of values of any integer type

          • 1 month ago
            Anonymous

            You are correct, but the difference between unspecified and implementation-defined is hairsplitting ("unspecified" shouldn't even exist in the standard, there's no point).

          • 1 month ago
            Anonymous

            in practice it's usually just "what gcc/clang compiles to on x86/arm"

          • 1 month ago
            Anonymous

            That's a really bad mindset to have. You should never rely on undefined behavior or compiler bugs, even if they work on your machine at the current moment.

          • 1 month ago
            Anonymous

            Rust people relies on LLVM just fine even with this 3-years old issue unresolved

          • 1 month ago
            Anonymous

            Implementation defined has to be consistent, unspecified doesn’t have to be.

          • 1 month ago
            Anonymous

            Unspecified just means the compiler or stdlib isn't required to document the behavior.

            That's a really bad mindset to have. You should never rely on undefined behavior or compiler bugs, even if they work on your machine at the current moment.

            unspecified and implementation-defined =/= UB
            Shifting a signed integer to the right is implementation-defined, but not UB.
            The order of evaluation of parameters is unspecified, but parameters aren't UB.

          • 1 month ago
            Anonymous

            >Unspecified just means the compiler or stdlib isn't required to document the behavior.
            And there's no point to that, just make everything implementation-defined (even if the definition ends up being "frick off we're not telling you").

          • 1 month ago
            Anonymous

            It wouldn’t matter if this was UB, as the result is identical.

          • 1 month ago
            Anonymous

            UB that just "works" is still UB and can stop working at any point.

          • 1 month ago
            Anonymous

            There are only two outcomes, either is valid. This is exactly why UB exists, because it allows for an optimisation is some cases.

          • 1 month ago
            Anonymous

            there are more than two outcomes from point of view of compiler upkeeper.
            if something is UB then it's 3rd option known as it's known and nobody cares.

          • 1 month ago
            Anonymous

            Code invoking UB is not valid.

            The UB here is that the pointer may be invalidated, this doesn’t stop it from being a number.

          • 1 month ago
            Anonymous

            what are you talking about?
            address of pointer is different. you are literally taking two different variables and you are flabbergasted why isn't it pointing to the same place.

          • 1 month ago
            Anonymous

            ?

          • 1 month ago
            Anonymous

            you use godbolt.
            check assembly code.
            do your v have the same address as each other?
            do your pointer have the same address as each other?

            no they do not because you declared two different variables and names them the same in their own local environments.

          • 1 month ago
            Anonymous

            You responded to the wrong post, or confused me with someone else, hence the "?".

          • 1 month ago
            Anonymous

            it's not even UB its fully defined, I don't understand what is the problem here.

          • 1 month ago
            Anonymous

            Assuming that the relative position of a pointer has meaning is UB, it doesn’t matter because the code doesn’t rely on this being the case.

          • 1 month ago
            Anonymous

            Code invoking UB is not valid.

          • 1 month ago
            Anonymous

            Imagine the following:
            char a[10] = {0};
            char b[10] = {0};
            char *c = some_condition() ? a : b;
            memmove(a, c + 2, 5);
            if (c == b) {
            ...
            }
            The compiler could notice that memmove() is UB to call on separate allocations, and infer that a and c must be the same allocation, and therefore c == a and c != b, and remove the whole block.

          • 1 month ago
            Anonymous

            the pointers are cast to integers prior to comparison, you even said so yourself.
            comparing integers is not UB.

          • 1 month ago
            Anonymous

            It's not UB but if it was then that would matter (contra the post I replied to)

          • 1 month ago
            Anonymous

            It's probably not UB but a compiler bug for Rust and UB or correct behavior for C++ (not sure cause I haven't read the standard)

            >You need a specification to determine if it's a compiler bug or not.
            You don't need a specification to determine that two integers with equal values should be equal.

            If Rust treats pointers as integers as you said it's a Rust compiler bug. But there is no legal document saying so (I think)

          • 1 month ago
            Anonymous

            >If Rust treats pointers as integers as you said it's a Rust compiler bug.
            The pointers are cast to integers and those integers are then compared.
            dumb moron.

          • 1 month ago
            Anonymous

            So what does Rust say about comparing pointers to variables in different scopes after all

          • 1 month ago
            Anonymous

            how is this relevant?

          • 1 month ago
            Anonymous

            Okay if Rust says you can cast them to integers and then compare integers, then if they point to the same address it should return true regardless (even in the example of different functions I stated earlier to another poster, tho I'm not sure if it's doable in Rust due to ownership etc.) and this is a bug in the Rust compiler. However since there is no specification we can't be absolute about this because Rust is undefined (in a way that matters to compilers)

          • 1 month ago
            Anonymous

            >Rust says you can cast them to integers
            you can
            https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#type-cast-expressions
            >then compare integers
            you can
            https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#comparison-operators
            >then if they point to the same address
            integer don't point to anything
            >and this is a bug in the Rust compiler
            it is
            https://github.com/rust-lang/rust/issues/107975
            >since there is no specification
            You don't need a specification to determine that two integers with equal values should be equal.

          • 1 month ago
            Anonymous

            >integer don't point to anything
            so where do you get the assumption that they are equal if they don't point to anything in the first place?

          • 1 month ago
            Anonymous

            because they have the same value.
            140725496097704 == 140725496097704

          • 1 month ago
            Anonymous

            >You don't need a specification to determine that two integers with equal values should be equal.
            If you are being reasonable that is. Technically one could define a language in which 1 + 1 evaluates to 3. Also the docs are good enough to justify that it is a bug until a formal specification is created

            The LLVM people say this is a bug in LLVM, I think it's considered buggy by C and C++. By now ITT we've looked at the C standard and there's nothing to suggest pointer UB carries on beyond a conversion to an integer.
            And it's definitely considered buggy by Rust because if you take it a few steps further you can use it to produce UB (with segfaults and everything), which goes against Rust's documented guarantees. Rust doesn't have a full spec yet the way C and C++ do (they're working on it) but it has always specified plenty.

            According to

            frick
            >6.3.2.3p6
            >Any pointer type may be converted to an integer type. Except as previously specified, the result
            >is implementation-defined. If the result cannot be represented in the integer type, the behavior is
            >undefined. The result need not be in the range of values of any integer type

            converting pointers to integers is unspecified in C++ (likely also in C) as rhe other poster was correctly claiming. According to it's a bug in rustc. I'm very inteterested in seeing how LLVM deals with it. I don't know much about LLVM but it seems to me that it shouldn't be a bug because LLVM gives you seperate pointers for each variable (even the local ones). However there may be a bug when LLVM puts the variables in the same address during an optimization pass and then maybe forgets to set the value pointers equal? But how would that even happen? Have they reproduced the bug in LLVM ir?

          • 1 month ago
            Anonymous

            >it's a bug in rustc
            it's a bug in LLVM
            https://github.com/llvm/llvm-project/issues/45725

          • 1 month ago
            Anonymous

            LLVM has lifetimes? Damn. I didn't read the whole thing and it isn't exactly what I had in mind. I was thinking of a more direct translation of the rust program because that example has it's flaws (pointed out like branch A won't ever be taken, I don't know how lifetimes work in LLVM but it seems they were using p after it's end etc.). Didn't read in detail but wouldn't the solution be make the pass that does this optimization after making the pass which merges compatible variables? They can be interacting tho. Or does it not work like that and LLVM requires lowering to place variables in the same address? It seems that would mean this optimization would have to be disabled. If a direct translation of the Rust program was used then it would demonstrate if it's an LLVM bug or not better. I'm still not fully convinced that rustc didn't just missuse LLVM for it's thing (because the example had it's flaws)

            Adding onto [...], I think you're supposed to store them in a struct and manually declare that the struct is Send/Sync. There's something similar with UnsafeCell, which isn't Sync either. Bit annoying if you're not building an abstraction though.
            I had to opt out of Send/Sync once and I think I did it by adding a PhantomData<Rc<()>> member. Very ugly and unintuitive, it does make sense that they favor opt-in over opt-out.

            [...]
            It's implementation-defined, so it doesn't give you permission to emit fricked-up evil integers. You can't predict which integers you get but once you have the integers they should be well-behaved. Unless you can do a weird reading based on trap representations but that's now what these compilers are going for anyway, they want to let you access the actual address as an integer.
            It's a bug in rustc insofar as you can run into this bug when you use rustc. It's not actually a bug in rustc's own code, it's a LLVM bug.

            [...]
            [...]
            Huh, and with v[2] it correctly says "true". They must have fixed something recently. I don't yet trust that they completely fixed it but I tried a few things and can't make it slip up.

            >It's not actually a bug in rustc's own code, it's a LLVM bug.
            See above if you want
            >it doesn't give you permission to emit fricked-up evil integers
            How will I (legally) troll you programmers then? Nah but seriously it means the implementation can give you integers which are not equal under any circumstances if it wants and there is no requirement the implentation should let you know if it decided to place two variables of different scope in the same address much like how it isn't obliged to inform you that two variables got in the same register because they aren't used together etc.

          • 1 month ago
            Anonymous

            >Nah but seriously it means the implementation can give you integers which are not equal under any circumstances
            It can give you integers which are equal, and it can give you integers which aren't equal, but it has to choose. Right now it gives you integers which both are and aren't equal at the same time, that's bogus.

          • 1 month ago
            Anonymous

            Well if you put it like that then it looks like a bug in the implementation. Moreso because you could transform a and b in any other way to make it impossible to predict the result at compile time and then compare them again and get true. It depends on wether this was the implementation's intended behavior. I suggest you try that and let us know, it would be funny if it works. Maybe something like
            volatile uintptr_t c = a, d = b;
            c == b

            If that's how volatile works. Nonetheless it seems that if you declared a and b correctly volatile from the begining as they really are then you will probably get the desired behavior. So I would say this is more of an error on the part of the programmer not knowing that a and b are unspecified and therefore need to be declared volatile to do what they want. And nobody in the thread pointed that out lol (and I only thought of it now, I guess we all suck at programming)

          • 1 month ago
            Anonymous

            volatile does fix this, but it shouldn't be necessary. It forces the compiler to pretend that the values might have changed between the write and the read (which forces the comparison to take place at runtime) but it's impossible that they actually changed. If it works with volatile then it should work without volatile.
            You found a workaround but not the actual root of the problem.

            [...]
            Wait LLVM also has volatile I think so is this just the fix rustc needs to deal with the bug? If so I'm leaning on the it's a rustc bug, not LLVM

            Preventing most compiler optimizations just in case isn't a reasonable option.
            LLVM's authors consider this a LLVM bug so I'm not sure why you don't?

          • 1 month ago
            Anonymous

            >but it's impossible that they actually changed
            Technically they do change when the optimiser changes the addresses of the variables but this is very internal, probably not what volatile is intended for. I would say the situation in general is weird. Originally you can't compare these pointers so cast them to integers and compare them then so maybe volatile should be used?

            >If it works with volatile then it should work without volatile.
            What do you mean?
            >Preventing most compiler optimizations just in case isn't a reasonable option.
            I see
            >LLVM's authors consider this a LLVM bug so I'm not sure why you don't?
            I just don't know enough about LLVM to accept it's making a mistake. I usually wouldn't blame the tool because that's a bad way of thinking. I may have to read through the LLVM issue in github to understand why the devs said it's a bug. I was hopong for a more flear example

            >In this case, the compiler assumes you're a Black person misusing addresses to data that is already freed/unreachable so it generated code that will always make it false.
            wrong. look at the x86 output
            >sub rsp, 32
            >...
            >mov DWORD PTR [rbp-24], 0
            >mov DWORD PTR [rbp-20], 0
            >mov DWORD PTR [rbp-32], 0
            >mov DWORD PTR [rbp-28], 0
            >...
            >lea rax, [rbp-24]
            >mov QWORD PTR [rbp-8], rax
            >...
            >lea rax, [rbp-32]
            >mov QWORD PTR [rbp-16], rax
            >...
            >mov rax, QWORD PTR [rbp-8]
            >cmp rax, QWORD PTR [rbp-16]
            the compiler doesn't push or pop the stack for the two nested scopes. people just assumed it should

            >the compiler doesn't push or pop the stack for the two nested scopes. people just assumed it should
            Didn't read but I wanna add that scopes are more of a semantic part of a languge and aren't poped or pushed because I think this would make implementation significantly harder. The stack is used in most languages to push and pop stack frames which contain the local variables and arguments of functions only (plus some things that might happen due to optimisations)

          • 1 month ago
            Anonymous

            volatile does fix this, but it shouldn't be necessary. It forces the compiler to pretend that the values might have changed between the write and the read (which forces the comparison to take place at runtime) but it's impossible that they actually changed. If it works with volatile then it should work without volatile.
            You found a workaround but not the actual root of the problem.

            [...]
            Preventing most compiler optimizations just in case isn't a reasonable option.
            LLVM's authors consider this a LLVM bug so I'm not sure why you don't?

            >>LLVM's authors consider this a LLVM bug so I'm not sure why you don't?
            Because LLVM was and is funded by Apple so by extension it’s staffed by clueless troons resulting from COC diversity quotas.

          • 1 month ago
            Anonymous

            >Technically they do change when the optimiser changes the addresses of the variables
            That's not a change that occurs between the write and the read.
            >>If it works with volatile then it should work without volatile.
            >What do you mean?
            Volatile makes it do something at runtime that it'd otherwise do at compile time, but those two strategies should give the same result. (Unless there's UB but there isn't.)
            >I just don't know enough about LLVM to accept it's making a mistake. I usually wouldn't blame the tool because that's a bad way of thinking.
            LLVM has lots of bugs and so do all the good optimizing compilers, it's just that almost all the bugs you're likely to run into have already been found and fixed long ago. If they think it's a bug it's fair to assume it's a bug.
            >I may have to read through the LLVM issue in github to understand why the devs said it's a bug. I was hopong for a more flear example
            Pointers have weird rules but there's no reason for integers to be this unreliable.
            Does this one help?
            #include <stdio.h>
            #include <stdint.h>
            #include <stdlib.h>

            // WARNING: arg must not be 0!!!!
            void __attribute__((noinline)) dangerous_procedure(long arg) {
            printf("called dangerous_procedure() with arg = %ldn", arg);
            if (arg == 0) {
            puts("rm -rf /");
            }
            }

            int main() {
            uintptr_t a;
            uintptr_t b;
            {
            int v[2] = {0, 0};
            a = (uintptr_t) &v[0];
            }
            {
            int v[2] = {0, 0};
            b = (uintptr_t) &v[0];
            }
            long diff = a - b;
            if (diff != 0) {
            dangerous_procedure(diff);
            }
            }
            Output (clang trunk with -O):
            called dangerous_procedure() with arg = 0
            rm -rf /
            It optimized out the diff != 0 check and then passed 0 to the function anyway. That's plainly bad.

            [...]
            >>LLVM's authors consider this a LLVM bug so I'm not sure why you don't?
            Because LLVM was and is funded by Apple so by extension it’s staffed by clueless troons resulting from COC diversity quotas.

            See above. Is this reasonable?

          • 1 month ago
            Anonymous

            Well if you put it like that then it looks like a bug in the implementation. Moreso because you could transform a and b in any other way to make it impossible to predict the result at compile time and then compare them again and get true. It depends on wether this was the implementation's intended behavior. I suggest you try that and let us know, it would be funny if it works. Maybe something like
            volatile uintptr_t c = a, d = b;
            c == b

            If that's how volatile works. Nonetheless it seems that if you declared a and b correctly volatile from the begining as they really are then you will probably get the desired behavior. So I would say this is more of an error on the part of the programmer not knowing that a and b are unspecified and therefore need to be declared volatile to do what they want. And nobody in the thread pointed that out lol (and I only thought of it now, I guess we all suck at programming)

            Wait LLVM also has volatile I think so is this just the fix rustc needs to deal with the bug? If so I'm leaning on the it's a rustc bug, not LLVM

          • 1 month ago
            Anonymous

            The LLVM people say this is a bug in LLVM, I think it's considered buggy by C and C++. By now ITT we've looked at the C standard and there's nothing to suggest pointer UB carries on beyond a conversion to an integer.
            And it's definitely considered buggy by Rust because if you take it a few steps further you can use it to produce UB (with segfaults and everything), which goes against Rust's documented guarantees. Rust doesn't have a full spec yet the way C and C++ do (they're working on it) but it has always specified plenty.

        • 1 month ago
          Anonymous

          I should add that the Rust counterpart is definitely a bug. Idk what the C++ standard says about treating pointers like numbers, but Rust absolutely does treat raw pointers as numbers (as long you don't do anything unsafe{} with it.)

    • 1 month ago
      Anonymous

      >Using these pointers is incorrect in the first place
      No, it is not, you are "caching" the memory addresses as unsigned integers and then performing an equality comparison.
      It is the compiler technically optimizing wrongly, by assuming that a and b point to different addresses, even if in practice they aren't.

    • 1 month ago
      Anonymous

      The pointers ARE equal (OP pic unrelated), but the compiler incorrectly assumes that they aren't.
      >Interested in the Rust version of the bug where it makes sense? If so it would be a Rust implementation bug
      It's the same bug. It happens in Rust because Rust uses LLVM. Don't ask me how GCC independently acquired this bug.

    • 1 month ago
      Anonymous

      They're converted to integers before they go out of scope. And naively you'd expect dangling pointers to only be invalid to dereference.
      In Rust you write basically the same thing.

      so whats happening there if b is unused its address is discarded if using -O?

      The first array goes out of scope before the lifetime of the second array begins, so it can reuse the memory.
      The pointers point to two different allocations so the optimizer treats them as unequal even though they happen to have the same address. (Even if you cast them to integers first.) But the hardware just goes by address and considers them equal.
      So if you can get one comparison to be evaluated by the compiler and another by the hardware you get an inconsistency.

      >Using these pointers is incorrect in the first place
      No, it is not, you are "caching" the memory addresses as unsigned integers and then performing an equality comparison.
      It is the compiler technically optimizing wrongly, by assuming that a and b point to different addresses, even if in practice they aren't.

      >It is the compiler technically optimizing wrongly, by assuming that a and b point to different addresses
      It actually is allowed to do this up to a point. I don't remember if it's technically valid to take it this far but the standard defines pointers very abstractly.
      The reason optimizations like these are useful is that you want to know whether anyone else might be looking at a value. If you know that a value can't be unexpectedly mutated through some far-off pointer then you can perform a lot more optimizations. But if it were possible to guess a variable's address then that goes out of the window, you can never be sure that some other code didn't manage to guess a pointer and mutate the value anyway.

      Using actual pointers prevents this bug. Casting to uintptr_t (an integer type) is the cause.
      #include <stdio.h>
      #include <stdint.h>

      int main(){
      int* a;
      int* b;
      {
      int v[2] = {0, 0};
      a = &v[0];
      }
      {
      int v[2] = {0, 0};
      b = &v[0];
      }
      printf(
      "%p == %p evaluates to %sn",
      a,
      b,
      a == b ? "true" : "false"
      );
      }

      Works in C with -O3.
      Looks like Rust just sucks.

      You just have to jiggle it a bit.
      #include <stdio.h>
      #include <stdint.h>

      int *get_ptr() {
      int v[2] = {0, 0};
      return &v[0];
      }

      int main() {
      int* a = get_ptr();
      int* b = get_ptr();
      printf(
      "%p == %p evaluates to %sn",
      a,
      b,
      a == b ? "true" : "false"
      );
      }
      0x7fffa6f8b4d0 == 0x7fffa6f8b4d0 evaluates to false
      This one works with both int * and uintptr_t.

      • 1 month ago
        Anonymous

        That warns you that you're being moronic and the result is completely different.

        • 1 month ago
          Anonymous

          I did it on clang with -O like

          >This one works with both int * and uintptr_t.
          This one works for me both in gcc 13.2
          >(nil) == (nil) evaluates to true
          and clang 17.0.1
          >0x7ffe01d4e328 == 0x7ffe01d4e330 evaluates to false
          both with -O3.
          Thoughbeit, using just -O instead of -O3 makes it break in clang, but not gcc. Very arcane and mysterious stuff.

          , I guess it's pretty fragile.
          clang also has the warning, but even with that warning this is unexpected.

          Can't you just make it a 10 sec tiktok? I'm a zoomer so I can't focus on text
          [...]
          >"caching" the memory addresses as unsigned integers
          No because the types of a and b are pointers to unsigned integers if I understand correctly so you did not store two integers. Also even if you did save them as integers:
          [...]
          >The pointers ARE equal
          I'm not convinced. Does the languahe specification say that pointers to variables that are out of scope can be equal or is it undefined behavior?
          >Don't ask me how GCC independently acquired this bug.
          I suspect because it's probably undefined behavior, likely for both C++ and LLVM
          [...]
          >They're converted to integers before they go out of scope. And naively you'd expect dangling pointers to only be invalid to dereference.
          Does the C++ specification say any of these statements?

          >Does the C++ specification say any of these statements?
          The first statement is just a factual description of how the code is written. It performs the cast before the end of the lifetime.
          The second statement includes the word "naively" for a reason. There's an astonishing number of things that are invalid to do even with live pointers.

          if it's a llvm bug, why does is its also present in gcc?

          They often independently invent the same bugs.

          • 1 month ago
            Anonymous

            GCC works correctly with -O, -O1, -O2, and -O3.
            Not bothering with a screenshot because they're all identical.

          • 1 month ago
            Anonymous

            Try this one:
            #include <stdio.h>
            #include <stdint.h>

            int main(){
            int* a;
            int* b;
            {
            int v[2] = {0, 0};
            a = &v[0] + 2;
            }
            {
            int v[2] = {0, 0};
            b = &v[0];
            }
            printf(
            "%p == %p evaluates to %sn",
            a,
            b,
            a == b ? "true" : "false"
            );
            }

            I should add that the Rust counterpart is definitely a bug. Idk what the C++ standard says about treating pointers like numbers, but Rust absolutely does treat raw pointers as numbers (as long you don't do anything unsafe{} with it.)

            They're working on strict provenance to explicitly make them more than just numbers.

            I see. So the questions now are if pointers in this example can be equal and if casting unequal pointers to integers can produce equal integers
            [...]
            >The first statement is just a factual description of how the code is written.
            Yes I did not know about the uintptr_t type sorry
            [...]
            >The second statement includes the word "naively" for a reason.
            So it may be a bug on the part of the programmer not the compiler, right?
            [...]
            I can't find the standard or I'd look into it
            [...]
            Rust doesn't have a specification I think so I guess we can't answer. LLVM tho I think assumes all variables are stored in a different address regardless so if that's the case that's what Rust does

            >So it may be a bug on the part of the programmer not the compiler, right?
            I'm not sure but I think this might still be a compiler bug. If this is a bug on the part of the programmer then I don't know where the UB is supposed to be introduced. Is it when you cast the pointers to integers? Or do integers carry along secret provenance information?

      • 1 month ago
        Anonymous

        >This one works with both int * and uintptr_t.
        This one works for me both in gcc 13.2
        >(nil) == (nil) evaluates to true
        and clang 17.0.1
        >0x7ffe01d4e328 == 0x7ffe01d4e330 evaluates to false
        both with -O3.
        Thoughbeit, using just -O instead of -O3 makes it break in clang, but not gcc. Very arcane and mysterious stuff.

  23. 1 month ago
    Anonymous

    this works even if you cast the pointers to integers
    relevant LLVM bug report: https://github.com/llvm/llvm-project/issues/45725

    • 1 month ago
      Anonymous

      nvm, I'm moronic.

      • 1 month ago
        Anonymous

        nvm, I'm not moronic

    • 1 month ago
      Anonymous

      does it affect MSVC too

      • 1 month ago
        Anonymous

        Rust don't use MSVC as backend

        • 1 month ago
          Anonymous

          This bug doesn't affect only Rust. It's an LLVM/GCC bug.

          • 1 month ago
            Anonymous

            It affect only Rust because only Rust users consider it a bug

          • 1 month ago
            Anonymous

            brainlet

        • 1 month ago
          Anonymous

          oh yes sorry I'm asking if the optim bug is also present for C or CPP on msvc as it seems to affect LLVM and GCC too

      • 1 month ago
        Anonymous

        yep
        947776060928 == 947776060928 -> false

  24. 1 month ago
    Anonymous

    Using actual pointers prevents this bug. Casting to uintptr_t (an integer type) is the cause.
    #include <stdio.h>
    #include <stdint.h>

    int main(){
    int* a;
    int* b;
    {
    int v[2] = {0, 0};
    a = &v[0];
    }
    {
    int v[2] = {0, 0};
    b = &v[0];
    }
    printf(
    "%p == %p evaluates to %sn",
    a,
    b,
    a == b ? "true" : "false"
    );
    }

    • 1 month ago
      Anonymous

      wrong

      • 1 month ago
        Anonymous

        Works in C with -O3.
        Looks like Rust just sucks.

  25. 1 month ago
    Anonymous

    A moron compares pointers.

    Reassigns the array (there is no FP style binding shadowing as in Python) with a literal, which isn't the same value.

    Compiler optimized some shit away.

    Again, there is no location-based equality in C++.

    Meaningless code -- meaningless results.

    https://schiptsov.github.io/programming/understanding_cpp.html

  26. 1 month ago
    Anonymous

    >Have you ever noticed this bug?
    Yes, we had multiple threads per day about this bug for like 2 weeks when it was discovered. Only newbies don't remember it.

    The more important question is, why they haven't fixed it yet.

    • 1 month ago
      Anonymous

      >why they haven't fixed it yet.
      Probably because you have to do some really moronic stuff to make it happen.

    • 1 month ago
      Anonymous

      >why they haven't fixed it yet

      this works even if you cast the pointers to integers
      relevant LLVM bug report: https://github.com/llvm/llvm-project/issues/45725

  27. 1 month ago
    Anonymous

    what bug?

    • 1 month ago
      Anonymous

      Read the thread.

      [...]
      The bug happens when you enable optimizations, OP is some kind of advanced troll
      (The bug also exists in Rust with the LLVM backend and IIRC that's where this exact code first got publicized)

      • 1 month ago
        Anonymous

        I did, what bug tho.
        what do you expect program to do and what is different?

        • 1 month ago
          Anonymous

          this works even if you cast the pointers to integers
          relevant LLVM bug report: https://github.com/llvm/llvm-project/issues/45725

          • 1 month ago
            Anonymous

            I do not think you understand the question.
            what is the compiler rule that is being violated, can you show that? is this compiler error or is this knowledge gap?

          • 1 month ago
            Anonymous

            In the OP no rule is violated.

            [...]
            The bug happens when you enable optimizations, OP is some kind of advanced troll
            (The bug also exists in Rust with the LLVM backend and IIRC that's where this exact code first got publicized)

            here, two equal integer compare inequal.

          • 1 month ago
            Anonymous

            that is not how you determine compiler errors.
            every compiler has its own set of rules and assumptions. you have to go to your compiler documentation and find where it talks about your problem and present your bug relative to that rule.

  28. 1 month ago
    Anonymous

    Zig: hold my beer
    https://github.com/ziglang/zig/issues/16343

  29. 1 month ago
    Anonymous

    there is no bug here. there is no guarantee the second instance of v will have the same address as the first one.

    • 1 month ago
      Anonymous

      dumb moron

      • 1 month ago
        Anonymous

        explain

  30. 1 month ago
    Anonymous

    >(uintptr_t) & v[0]

  31. 1 month ago
    Anonymous

    I'll be the first cnile to mention that, if you so desperately want a guaranteed stack slot de-allocation, try VLA

  32. 1 month ago
    Anonymous

    Seems like this only causes problems with memelangs.

    • 1 month ago
      Anonymous

      yeah it's almost like they are stirring shit to troll LLVM devs

  33. 1 month ago
    Anonymous

    >fails at bait
    >somehow still successful
    my fedora got tipped

    • 1 month ago
      Anonymous

      Honestly an amazing bait thread
      >OP posts moronic code which isn't worth discussion in the first place
      >Purposely fricks up the results
      >Anons run it themselves to discover the actual "bug"
      >"volatile" is only mentioned hours later and is disregarded in various ways

      • 1 month ago
        Anonymous

        dumb moron
        it's a compiler bug
        wtf does volatile have to do with anything?

  34. 1 month ago
    Anonymous

    Well played OP. That was very intelligent of you to pretend to be moronic for the first 30 posts intentionally to bait people to reply to your thread. *tips hat to you*

    • 1 month ago
      Anonymous

      Nah, it's good that OP is bringing this up.

      I personally assumed it had been fixed long time ago since it has been quite some time since it was discovered.

  35. 1 month ago
    Anonymous

    Works as it should on my MacBook M1
    Apple wins again

    • 1 month ago
      Anonymous

      Yeah, on my M1 I tested with gcc, clang, zig, and rust.
      I get different addresses -> false
      Maybe use a real OS LOL

      • 1 month ago
        Anonymous

        >gcc
        which gcc? If you use the GCC you get from XCode that's not GCC, it's clang because Apple is that moronic

    • 1 month ago
      Anonymous

      Yeah, on my M1 I tested with gcc, clang, zig, and rust.
      I get different addresses -> false
      Maybe use a real OS LOL

      This just means the compiler isn't optimizing your code kek. "I run unoptimized code on my machine" what a win.

  36. 1 month ago
    Anonymous

    Wait until you find out Cranelift does it too

  37. 1 month ago
    Anonymous

    Nobody is correcting this because the code does not make any kind of sense

  38. 1 month ago
    Anonymous

    OH NO NO NO NO c sisters...

    • 1 month ago
      Anonymous

      You didn't even read the post.

  39. 1 month ago
    Anonymous

    Mac sisters... we are winning...

    • 1 month ago
      Anonymous

      you get exactly what is expected on C, two different variables occupying two different memory addresses.
      why do you expect something else?

  40. 1 month ago
    Anonymous

    gcc trunk (14+?) looks fine now
    https://godbolt.org/z/rbePhz586

    • 1 month ago
      Anonymous

      #include <stdio.h>
      #include <stdint.h>

      int main() {
      volatile int i = 0;
      uintptr_t a;
      uintptr_t b;
      {
      int v[2] = {0, 0};
      a = (uintptr_t) &v[i];
      }
      {
      int v[2] = {0, 0};
      b = (uintptr_t) &v[i];
      }
      printf(
      "%ld == %ld %s",
      a,
      b,
      a == b ? "true" : "false"
      );
      }

  41. 1 month ago
    Anonymous

    >C-style casting

    • 1 month ago
      Anonymous

      >>C-

    • 1 month ago
      Anonymous

      >>C-

      Is that the prequel or the sequel to C--?

  42. 1 month ago
    Anonymous

    I don't get it. it makes sense. it even increments exactly by 8.

    • 1 month ago
      Anonymous

      read the thread, dumb moron

    • 1 month ago
      Anonymous

      It does, depending how you want to satisfy the programmer's code based on the rules of C / C++. There are multiple correct answers.

  43. 1 month ago
    Anonymous

    FFS This has to be bait. Only a moron not understanding pointers and scope would see a bug here.

  44. 1 month ago
    Anonymous

    >redefines array
    >compares addresses
    >claims it's the same as comparing values
    >must be compiler bug

  45. 1 month ago
    Anonymous

    >range 0,0
    >initial 0
    >returned 0
    I don't see a problem here. You've asked the computa to evaluate a 0 and it returned a 0. Logical. Works as intented.
    >evaluates to false
    because a computa is trying to tell you, that you're wasting your time on bullshit and it is a false thing to do with your life.
    >

  46. 1 month ago
    Anonymous

    Good morning sirs,
    Java Enterprise Programmer here.
    you should be doing the equals()

    also why are you in the first place doing two same-looking but identifiably separate initializations and then comparing their pointers?

    • 1 month ago
      Anonymous

      read the thread, dumb moron

  47. 1 month ago
    Anonymous

    Am I moronic or compiler just allocates on stack 2 arrays of 2 integer values and code compares addresses of starting element of each array?
    Of course without optimizations compiler will allocate them at different locations.
    Was this supposed to be some gotcha?
    >t. c moron.

    • 1 month ago
      Anonymous

      read the thread, dumb moron

      • 1 month ago
        Anonymous

        >dumb moron
        it's redundant.
        please provide qrd.

        • 1 month ago
          Anonymous

          read the first 25 posts

          • 1 month ago
            Anonymous

            so why did you call me dumb moron if I was right in the end?

          • 1 month ago
            Anonymous

            you are not right

            ITT: blind people and rustrannies

            read the thread, dumb moron

          • 1 month ago
            Anonymous

            >you are not right
            stop trolling and provide argument.

          • 1 month ago
            Anonymous

            https://godbolt.org/z/covcE7hEr

        • 1 month ago
          Anonymous

          ITT: blind people and rustrannies

          >allocating 8 bytes to the stack and taking the address of the first byte
          >allocating another 8 bytes to the stack and again taking the address of the first byte
          >surprised when the two addresses are not equal

          See

          [...]
          The bug happens when you enable optimizations, OP is some kind of advanced troll
          (The bug also exists in Rust with the LLVM backend and IIRC that's where this exact code first got publicized)

  48. 1 month ago
    Anonymous

    ITT: blind people and rustrannies

    • 1 month ago
      Anonymous

      Turn on optimizations, shitlord
      OP is too dumb to know how to do that but maybe you can figure it out if you have enough brain cells to be able to breathe

  49. 1 month ago
    Anonymous

    >compare pointers, which always get fricked over by cooooompilers oooooptimizing
    Really.

    • 1 month ago
      Anonymous

      >allocating 8 bytes to the stack and taking the address of the first byte
      >allocating another 8 bytes to the stack and again taking the address of the first byte
      >surprised when the two addresses are not equal

      >(uintptr_t)
      dumb morons

  50. 1 month ago
    Anonymous

    >allocating 8 bytes to the stack and taking the address of the first byte
    >allocating another 8 bytes to the stack and again taking the address of the first byte
    >surprised when the two addresses are not equal

  51. 1 month ago
    Anonymous

    >ITT: moronic anons gaslighting other anons into believing that wrong is right
    only on IQfy

  52. 1 month ago
    Anonymous

    #include <stdio.h>
    #include <stdint.h>

    int main()
    {
    uintptr_t a;
    uintptr_t b;

    {
    int v[2] = {0, 0};
    a = (uintptr_t) &v[0];
    }
    {
    int v[2] = {0, 0};
    b = (uintptr_t) &v[0];
    }

    printf("%ld == %ld is %sn",
    a,
    b,
    a == b ? "true" : "false");
    return 0;
    }
    140722251550048 == 140722251550048 is true

    musl
    gcc 12.2.1

    • 1 month ago
      Anonymous

      -O3 makes it:
      140733851110288 == 140733851110288 is false

    • 1 month ago
      Anonymous

      -O3 makes it:
      140733851110288 == 140733851110288 is false

      all the major compilers do this: MSVC, Clang/LLVM, GCC, Apple Clang/LLVM.
      it makes sense they all have the same bug since they probably all read and impl the same research. The bug is pretty harmless though, just don't do Black personlicious things to pointer addresses as integers. I doubt it's getting fixed anytime soon.

      • 1 month ago
        Anonymous

        Can't reproduce it on GCC trunk, seems like they fixed it

      • 1 month ago
        Anonymous

        [...]
        [...]
        adding volatile keyword to variable declarations returns
        140731245895056 == 140731245895056 is true

        both with optimizations and without them.

        just to add, if you're doing Black personlicious things add appropriate keywords to variable declarations.

      • 1 month ago
        Anonymous

        >all the major compilers do this: MSVC
        proof?

        [...]
        just to add, if you're doing Black personlicious things add appropriate keywords to variable declarations.

        >add appropriate keywords to variable declarations
        which ones?

        • 1 month ago
          Anonymous

          int main()
          {
          volatile uintptr_t a;
          volatile uintptr_t b;
          }

          it prevents compiler from early evaluation of expressions.

          • 1 month ago
            Anonymous

            volatile is not an appropriate keyword here.

          • 1 month ago
            Anonymous

            ok, which one would be appropriate?
            I've added it because it made sense to me, it forbids compiler to do nasty optimization things. Maybe I'm wrong using it, please provide better solution.

          • 1 month ago
            Anonymous

            >ok, which one would be appropriate?
            I asked you that question.
            dumb moron

          • 1 month ago
            Anonymous

            no you didn't.
            you just keep trolling this thread without providing anything of value to the discussion, please, kindly kys already and end your miserable existence.
            please and thanks.

          • 1 month ago
            Anonymous

            >no you didn't.

            >all the major compilers do this: MSVC
            proof?

            [...]
            >add appropriate keywords to variable declarations
            which ones?

            Hey bonus challenge:
            In C++ this is just unspecified and possibly undefined behaviour. However we established that a bug exists in LLVM and GCC behaves similarly. Is there a way to exploit the LLVM bug to cause a different bug in C++ with no undefined or unspecified behavior involved?
            Maybe not because it may require casting pointers to integers or comparing pointers directly which might be undefined behavior. Or there might be some cases in the standard where it's not undefined behavior and so we can use them?

            >In C++ this is just unspecified and possibly undefined behaviour.
            easy fix
            #include <stdio.h>
            #include <stdint.h>

            int main() {
            uintptr_t a;
            uintptr_t b;
            {
            int v[2] = {0, 0};
            a = (uintptr_t) (void*) &v[0];
            }
            {
            int v[2] = {0, 0};
            b = (uintptr_t) (void*) &v[0];
            }
            printf(
            "%ld == %ld %s",
            a,
            b,
            a == b ? "true" : "false"
            );
            }

          • 1 month ago
            Anonymous

            Preventing nasty optimizations is only a side effect. Semantically, it has different meaning:
            >the volatile keyword indicates that a value may change between different accesses, even if it does not appear to be modified
            It indicates that a variable can change on its own, independent of your program code. It's not a bandaid to fix a compiler bug.

            The appropriate way of dealing with it is not avoid using patterns that trigger this bug until compiler developers fix it.

          • 1 month ago
            Anonymous

            Well perhaps, I don't say it's the "right" thing to do.
            My initial response was that if you do Black personlicious things like OP, then add Black personlicious solutions or deal with Black personlicious consequences.
            I thought the point was to produce correct results.

        • 1 month ago
          Anonymous

          https://github.com/llvm/llvm-project/issues/45725#issuecomment-981029774 sez it happens on MSVC. You can't run MSVC programs on Godbolt but I can try to get MSVC set up locally to see if it still happens

        • 1 month ago
          Anonymous

          >proof?
          unsigned __int64 `__local_stdio_printf_options'::`2'::_OptionsStorage DQ 01H DUP (?) ; `__local_stdio_printf_options'::`2'::_OptionsStorage
          `string' DB '%ld ='
          DB '= %ld ', 0e2H, 086H, 092H, ' %s', 00H ; `string'
          `string' DB 'false', 00H ; `string'

          v$1 = 48
          v$2 = 48
          main PROC ; COMDAT
          $LN4:
          sub rsp, 40 ; 00000028H
          lea r9, OFFSET FLAT:`string'
          lea r8, QWORD PTR v$1[rsp]
          lea rdx, QWORD PTR v$2[rsp]
          lea rcx, OFFSET FLAT:`string'
          call printf
          xor eax, eax
          add rsp, 40 ; 00000028H
          ret 0
          main ENDP

          addresses are the same: rsp, and the string literal false is placed into the 3rd arg to printf.

        • 1 month ago
          Anonymous

          https://github.com/llvm/llvm-project/issues/45725#issuecomment-981029774 sez it happens on MSVC. You can't run MSVC programs on Godbolt but I can try to get MSVC set up locally to see if it still happens

          Figured out how to run MSVC and this is the output with /O2:
          474495055712 == 474495055712 false
          It has the bug

          • 1 month ago
            Anonymous

            Microsoft stealing code from open source projects confirmed

    • 1 month ago
      Anonymous

      -O3 makes it:
      140733851110288 == 140733851110288 is false

      [...]
      all the major compilers do this: MSVC, Clang/LLVM, GCC, Apple Clang/LLVM.
      it makes sense they all have the same bug since they probably all read and impl the same research. The bug is pretty harmless though, just don't do Black personlicious things to pointer addresses as integers. I doubt it's getting fixed anytime soon.

      adding volatile keyword to variable declarations returns
      140731245895056 == 140731245895056 is true

      both with optimizations and without them.

      • 1 month ago
        Anonymous

        I'm not surprised. You're effectively telling the compiler that spooky actions at a distance are happening when you declare variables volatile. It's not really intended for this case but works as a side effect of being an escape hatch for the unknowable.

        • 1 month ago
          Anonymous

          It made sense to use volatile here. Maybe I'm wrong, please correct me in that case.

          • 1 month ago
            Anonymous

            volatile is for memory mapped IO

          • 1 month ago
            Anonymous

            initially intended, but not restricted to
            https://en.wikipedia.org/wiki/Volatile_(computer_programming)#In_C_and_C++

  53. 1 month ago
    Anonymous

    After this thread I don't feel so bad that ai will replace 99.9% of anons here.
    kek

    • 1 month ago
      Anonymous

      sure bud

      • 1 month ago
        Anonymous

        stop seething and accept the inevitable.
        learn some actually employable skills.

  54. 1 month ago
    Anonymous

    only -O1 is broken for me, kek. other optimizations work as intended with -std=c++20.

  55. 1 month ago
    Anonymous
    • 1 month ago
      Anonymous

      this thread was some next-level bait
      with op unable to reproduce the bug
      in the first place

  56. 1 month ago
    Anonymous

    discuss

    • 1 month ago
      Anonymous

      there are already 285 posts discussing this
      dumb moron

      • 1 month ago
        Anonymous

        not enough

  57. 1 month ago
    Anonymous

    You took the address of the variable.

  58. 1 month ago
    Anonymous

    Its being years since i touched C++ but by looking at this the problem is pretty simple:

    a and b are variables storing the address of v[0]. Problem is,you declared v two times in two different blocks. Which means the compiler will chose two different addresses to store each array despite the same label.

    Your print is clearly showing that.

    • 1 month ago
      Anonymous

      read the thread, dumb moron

  59. 1 month ago
    Anonymous

    >obvious troll OP
    >319 replies
    picrel. These are the types of people who will be replaced by LLMs.

    • 1 month ago
      Anonymous

      >dumb moron believes a dumb and moronic "AI"
      guess what: ChatGPT got it wrong, a and b are the same if you enable optimizations
      you would have known that if you would have read the thread
      dumb moron

  60. 1 month ago
    Anonymous

    No real world C/C++ code is effected by this. Only LLVM memelangs suffer from this, so why should anyone care?

    • 1 month ago
      Anonymous

      What's your C/C++ compiler?

Your email address will not be published. Required fields are marked *