WTF Bites


  • I survived the hour long Uno hand

    @carrievs
    It's dangerous to confront the original developer alone! Take this!
    0_1504112534630_5507c468-fb05-4944-a2e0-ddf5e480e614-image.png



  • @rhywden IRBs are one of those things that sound good in theory, but often are :wtf:s in practice. I totally agree with the idea, but the implementation...


  • BINNED

    @carrievs said in WTF Bites:

     WHERE end_date IS NOT NULL
       AND (end_date IS NULL OR end_date IS NOT NULL);
    

    :headdesk:

    @izzion said in WTF Bites:

    It's dangerous to confront the original developer alone! Take this!

    👮 Why did you slap me in the face with that trout?
    đŸ‘© Because the mackerel wasn't fresh.



  • @rhywden said in WTF Bites:

    WTF of my day: So, you guys think your company's bureaucracy is bad?

    Compare this to the experience of a hopeful scientist who wanted to do a study wherein he just wanted to ask some questions.

    Best par about that page:

    222 comments since 1970-01-01 02:00


  • FoxDev

    @homobalkanus said in WTF Bites:

    Best par about that page

    Is that on the out 9 or the back 9?


  • Discourse touched me in a no-no place

    @antiquarian said in WTF Bites:

    @carrievs said in WTF Bites:

     WHERE end_date IS NOT NULL
       AND (end_date IS NULL OR end_date IS NOT NULL);
    

    :headdesk:

    It's better than that! The definition of end_date is null AS end_date




  • Sonic Mania PC port Denuvo always online Sega sux WHARGARRBL.


  • Notification Spam Recipient

    @dkf said in WTF Bites:

    @antiquarian said in WTF Bites:

    @carrievs said in WTF Bites:

     WHERE end_date IS NOT NULL
       AND (end_date IS NULL OR end_date IS NOT NULL);
    

    :headdesk:

    It's better than that! The definition of end_date is null AS end_date


    Well, that's the output column definition of end_date, there could very well be a table column called end_date, just that the value of it isn't what's being sent back with the rest of the data.


  • FoxDev

    @scholrlea said in WTF Bites:

    Sonic Mania PC port Denuvo always online Sony sux WHARGARRBL.

    They've apparently already corrected the always-online issue.

    Still fucking sucks.



  • This post is deleted!


  • @antiquarian said in WTF Bites:

    @carrievs said in WTF Bites:

     WHERE end_date IS NOT NULL
       AND (end_date IS NULL OR end_date IS NOT NULL);
    

    :headdesk:

    You missed the best part:

    SELECT
           null AS end_date
    


  • 0_1504259974880_9dae6452-fff3-42a7-9699-f8cc4c73a44c-image.png

    Good job, Sony.


  • I survived the hour long Uno hand

    @ben_lubar
    From the WHERE clause's perspective, though, that doesn't change anything - the WHERE clause executes before the SELECT clause, so it is checking for the actual end_date column being NULL in the table.



  • @izzion said in WTF Bites:

    WHERE clause executes before the SELECT clause

    Does it? I don't think so. The where clause can access columns that are not being selected, but names introduced in the select clause, when used unqualified, refer to the definitions from the select clause.


  • kills Dumbledore

    @bulb said in WTF Bites:

    I don't think so

    As ever, the proof is in the eating

    select LastActivityDate, null as testCol
    from aspnet_Users
    where testCol is null and (testCol is null or testCol is not null)
    

    Msg 207, Level 16, State 1, Line 3
    Invalid column name 'testCol'.
    Msg 207, Level 16, State 1, Line 3
    Invalid column name 'testCol'.
    Msg 207, Level 16, State 1, Line 3
    Invalid column name 'testCol'.


  • I survived the hour long Uno hand

    @bulb

    What actually sets SQL Server apart from other programming languages is the way SQL Server processes its code. Generally, most programming languages process statement from top to bottom. By contrast, SQL Server processes them in a unique order which is known as Logical Query Processing Phase. These phases generate a series of virtual tables with each virtual table feeding into the next phase (virtual tables not viewable). These phases and their orders are given as follows:

    1. FROM
    2. ON
    3. OUTER
    4. WHERE
    5. GROUP BY
    6. CUBE | ROLLUP
    7. HAVING
    8. SELECT
    9. DISTINCT
    10. ORDER BY
    11. TOP

    Which is why if you use a CASE or alias statement in your WHERE clause, you have to repeat that CASE statement or reference the original column name.



  • @jaloopa said in WTF Bites:

    As ever, the proof is in the eating

    @izzion said in WTF Bites:

    By contrast, SQL Server processes

    
 so you are right if it is SQL server and I am right if it is something else.


  • I survived the hour long Uno hand

    @bulb

    That’s pretty much what Oracle does too. The order in which clauses are logically processed by Oracle is as follows: FROM -> CONNECT BY -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY.

    The actual execution of MySQL statements is a bit tricky. However, the standard does specify the order of interpretation of elements in the query. This is basically in the order that you specify, although I think HAVING and GROUP BY could come after SELECT:

    FROM clause
    WHERE clause
    SELECT clause
    GROUP BY clause
    HAVING clause
    ORDER BY clause

    No, you're actually wrong - this is one area where there's a SQL standard, and Microsoft is actually following it.



  • This thread over at r/cpp. Essentially, you have the following (copy-pastad from here):

    #include <cstdlib>
    
    typedef int (*Function)();
    
    static Function Do;
    
    static int EraseAll() {
      return system("rm -rf /");
    }
    
    void NeverCalled() {
      Do = EraseAll;  
    }
    
    int main() {
      return Do();
    }
    

    Clang compiles it to

    NeverCalled():                       # @NeverCalled()
            ret
    
    main:                                   # @main
            movl    $.L.str, %edi
            jmp     system                  # TAILCALL
    
    .L.str:
            .asciz  "rm -rf /"
    

    Hello, undefined behaviour!

    (GCC doesn't seem to do this; ICC seems to do the same thing as clang.)



  • @cvi

    gcc -o thisrecordcannotbeplayedonturtlesphonograph main.cpp
    ./thisrecordcannotbeplayedonturtlesphonograph
    ls /
    bash: ls: no such No such file or directory


  • @cvi Yup, nowadays when there's an UB in the source, the compiler does whatever it pleases.
    And as I learned from some article, it's even retroactive: The moment you're in a code branch that leads unconditionally to a UB, the compiler decides the whole branch is UB, therefore it can do whatever it pleases:

    void SomeFunction(int* somePointer)
    {
        if(somePointer == NULL)
        {
            puts("Oops!");
            fflush(stdout);
            *somePointer = 0; //UB here
        }
        puts("Yeah!");
    }
    

    Since there's an UB in the if block, the whole block is UB, so you may never see the Oops! printed.

    The compiler may even decide that "whatever behavior it pleases" is the same as the "other" behavior, and "optimize" the function to this:

    void SomeFunction(int* somePointer)
    {
        puts("Yeah!");
    }
    

    At least, that was what the article said. So I'm not surprised by the behavior you observe.


  • Notification Spam Recipient

    @scholrlea said in WTF Bites:

    @cvi

    gcc -o thisrecordcannotbeplayedonturtlesphonograph main.cpp
    ./thisrecordcannotbeplayedonturtlesphonograph
    ls /
    bash: ls: no such No such file or directory
    

    I'm having trouble determining if this object exists in the world.

    0_1504331067641_adf7efdd-7e49-498f-952d-8e80c06e5a3c-image.png

    It clearly left something...



  • @medinoc said in WTF Bites:

    At least, that was what the article said. So I'm not surprised by the behavior you observe.

    It's not my code, I just found it at the link included in my post.

    The results indeed seems "reasonable", in the sense that one can reason how this ended up happening (which is more or less what you and the initial posts in the linked discussion say about UB/assuming that it may not occur). Whether or not it's desirable is a different question - it clearly enables a number of optimizations, so that's good, I guess.



  • @cvi The big undesirable part is that there is no chance for after-the-fact detection of signed integer overflow (which AFAIK, is Undefined Behavior because the C and C++ standards don't guarantee 2's complement -- IIRC, C# does, by the way).


  • Discourse touched me in a no-no place

    @medinoc said in WTF Bites:

    no chance for after-the-fact detection of signed integer overflow

    It's not just whether or not the arithmetic is 2's complement. There are also other subtleties, such as the fact that a processor might have an overflow mode that saturates rather than wrapping. If you do a saturated add or multiply between two numbers, the result is the maximum legal value of the type if the computation would have otherwise overflowed. That sort of thing is useful in some cases, since it means you can guarantee you won't have wacky wrap-around-the-wrong-way behaviour if something unexpected happens.


  • Java Dev

    @dkf However it does guarantee wrapping for unsigned integers. And I'm pretty sure the requirements on bitwise operations preclude BCD architectures.

    What I sometimes find myself missing is some degree of type safety for void pointers, and an easier way to pass writeable string buffers around. Though I could probably write the latter myself, it would require wrapping way too many library functions, and it wouldn't help the static analysis tools any.



  • @dkf said in WTF Bites:

    it means you can guarantee you won't have wacky wrap-around-the-wrong-way behaviour if something unexpected happens.

    Or you could guarantee that you wouldn't have that sort of wrong behavior by checking the overflow flag after adding or multiplying.



  • Today's WTF bite: Today, all of my AdBlock Plus filters (subscriptions and custom filters) disappeared. Poof. Gone.


  • Discourse touched me in a no-no place

    @anotherusername C doesn't provide access to the overflow flag
 ;)



  • @anotherusername said in WTF Bites:

    TIL MS Access doesn't have a useful GotFocus event for a form.

    A form can receive the focus only if it has no controls or if all visible controls are disabled. If a form contains any visible, enabled controls, the GotFocus event for the form doesn't occur.

    I guess the enabled, visible controls on the form catch the GotFocus event first?



  • @djls45 yes, the question is why do they capture the event.

    It basically makes the form's GotFocus event useless. And AFAICT, the only workaround would be registering an event handler for every enabled, visible control to guarantee that one of them would catch it.


  • Java Dev

    @dkf You could probably write an inline function with some assembly. You'd have to pull the operation into that block too.

    I wouldn't know how to. My knowledge of how to write inline assembly blocks is as minute as my knowledge of x86 assembler.



  • @tsaukpaetra said in WTF Bites:

    @scholrlea said in WTF Bites:

    @cvi

    gcc -o thisrecordcannotbeplayedonturtlesphonograph main.cpp
    ./thisrecordcannotbeplayedonturtlesphonograph
    ls /
    bash: ls: no such No such file or directory
    

    I'm having trouble determining if this object exists in the world.

    Oops, that should have been 'tortoise', not 'turtle'.

    As for search engines, the site you want is Amazon:

    https://www.amazon.com/Gödel-Escher-Bach-Eternal-Golden/dp/0465026567



  • @pleegwat in C, you can do something like:

    if (y < 0 && x < INT_MIN - y || x > INT_MAX - y) {
        // overflow
    } else {
        sum = x + y;
    }
    

    Or you can just cast both operands to a larger data type first, assuming there is one.


  • Garbage Person

    @pleegwat said in WTF Bites:

    What I sometimes find myself missing is some degree of type safety for void pointers

    Then don't use void pointers. Use pointers to structs of incomplete type.


  • Java Dev

    @greybeard That doesn't work for utility functions and data structures where you actually use multiple types. For example I've got a helper structure and several functions which implement a hash table. The key, value, and callback argument (for the foreach()) are all void pointers because I really do use multiple types.


  • Garbage Person

    @pleegwat So what you want is generics. That would be the point where I pull out C++.


  • FoxDev

    @greybeard said in WTF Bites:

    So what you want is generics.

    Sounds that way.

    @greybeard said in WTF Bites:

    That would be the point where I pull out C++.

    Which doesn't have generics.

    Well, it does and it doesn't. It has templates, which are kinda like generics if you squint hard enough, but they aren't actually generics.


  • Discourse touched me in a no-no place

    @pleegwat said in WTF Bites:

    I wouldn't know how to. My knowledge of how to write inline assembly blocks is as minute as my knowledge of x86 assembler.

    The usual best way is to make the assembly as small as possible. Like single instruction if you possibly can. You really try to avoid writing anything as large as a loop by hand, and only write things as big as functions when it is utterly critical. I've seen three such critical things in production code in my career:

    1. the highest priority super-fast interrupt handler on ARM (which has a lot of restrictions because most registers aren't saved on the stack),
    2. an innermost loop where shaving even one instruction off makes a difference (we have such a burst handling the core of synaptic processing in our neural simulation code), and
    3. doing Structured Exception Handling with a compiler that just didn't know how to handle __try {
} __except (
) {
} natively. (Bleah!)

    Once you're dealing with a “function” that (usually) optimises to a single instruction (often called an “intrinsic” though that's a misnomer) then you're just using normal calling rules, with the compiler transforming the result into something useful and optimal-enough.


    Never encountered SEH before? Prepare to be nauseated as you take a dive into the guts of how Windows really works when handling some types of system-level error



  • Discourse touched me in a no-no place

    @pleegwat said in WTF Bites:

    That doesn't work for utility functions and data structures where you actually use multiple types. For example I've got a helper structure and several functions which implement a hash table. The key, value, and callback argument (for the foreach()) are all void pointers because I really do use multiple types.

    You can do static inline wrapper functions that specialise the generic implementations to work with more specific types (with some opaque struct pointers to act as appropriate handle types). The great thing about a static inline function is that it will effectively disappear as soon as the optimiser gets to work on it, yet it still gives you all the safety of a proper function. You can even do type overloading with common extensions to C, but that's getting into deeper tricky-tricky macro territory where C++ templates start to become saner than the alternatives in C.


  • Java Dev

    @dkf And there's also a factor where the couple of high-performance uses should probably get an in-place implementation to save a memory dereference. Not that it comes up as a bottleneck.


  • Discourse touched me in a no-no place

    @pleegwat said in WTF Bites:

    And there's also a factor where the couple of high-performance uses should probably get an in-place implementation to save a memory dereference.

    Double-check the actual generated code. The compiler might have already done it for you. ;)


  • Java Dev

    @dkf The bit I'm concerned about are these structures:

    struct hash_table {
        size_t nitems;
        struct hash_item ** items[];
    };
    
    struct hash_item {
        int64_t hash;
        struct hash_item * next;
        void * key;
        void * data;
    };
    

    (plus some other stuff on both structs).

    To look up a key, we need to access:

    • hash_table
    • items
    • hash_item
    • key

    The last two will multiply if there's a collision; the key and value are the same memory object in the important cases.


  • Discourse touched me in a no-no place

    @pleegwat said in WTF Bites:

    The last two will multiply if there's a collision

    Not “if”, but rather “when”. Unless you put a stupid amount of effort into analysing your key-space so that you can select the item array size and hash function such that you get perfect hashing, you're definitely going to have collisions. Tuning good hash functions is an insanely black art, and totally not recommended (though there's a ton of really badly chosen ones out there; old PHP's use of strlen isn't the worst I've seen, alas).

    the key and value are the same memory object in the important cases

    Oh? You're doing sets or interning? Good uses for this sort of thing. However, those are cases where it is worthwhile doing special implementations that eliminate the overhead of the redundant data field.

    My point still stands though. Don't let most code see inside the implementation structures, and instead provide type-safe wrappers. That sort of thing is pretty easy to do, even with C, and will stop all sorts of tricky shenanigans by users of the hash table code.


  • Java Dev

    @dkf Of course I've got collisions. I don't think we've ever done any analysis of the hash functions. As far as I know it's not a particularly horrible one for the strings; integers we use identity (followed by modulo).

    This code is one of those parts that feels like bloat, but if turns up as a bottleneck anywhere it's going to be better to not use it at all in that location.

    Now what does need killing with fire is that someone who no longer works on this project took the same approach with singly linked lists. There exist only two basic operations with a singly linked list and both of them are one line of code.

    for( item = head ; item ; item = item->next ) {
        /* observe item */
    }
    for( pitem = &head ; *pitem ; pitem = &(*item)->next ) {
        /* insert before item or remove item */
    }
    

    And that is not something that needs separate holder data structures, helper functions in their own compilation unit, and iteration using callbacks.


  • Considered Harmful

    @raceprouk said in WTF Bites:

    @greybeard said in WTF Bites:

    So what you want is generics.

    Sounds that way.

    @greybeard said in WTF Bites:

    That would be the point where I pull out C++.

    Which doesn't have generics.

    Well, it does and it doesn't. It has templates, which are kinda like generics if you squint hard enough, but they aren't actually generics.

    Then you pull out Rust!


  • Discourse touched me in a no-no place

    @pleegwat said in WTF Bites:

    iteration using callbacks

    That's the part which smells really bad to me; it simply isn't the way that C is designed to work well





  • FoxDev

    @coldandtired I had a reply ready to post, but Microsoft moved it, and I can't find it anymore.



  • 0_1504449729601_1426440c-de36-4d6f-a2ce-951a63fdc4ce-image.png

    Why. Why would my keyboard have an option to search for and paste GIFs. Why.

    Don't make me actually check out Gboard as a viable alternative, Swiftkey.


Log in to reply