WTF Bites
-
@carrievs
It's dangerous to confront the original developer alone! Take this!
-
@rhywden IRBs are one of those things that sound good in theory, but often are s in practice. I totally agree with the idea, but the implementation...
-
WHERE end_date IS NOT NULL AND (end_date IS NULL OR end_date IS NOT NULL);
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.
-
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
-
-
@antiquarian said in WTF Bites:
WHERE end_date IS NOT NULL AND (end_date IS NULL OR end_date IS NOT NULL);
It's better than that! The definition of
end_date
isnull AS end_date
âŠ
-
Sonic Mania PC port Denuvo always online Sega sux WHARGARRBL.
-
@antiquarian said in WTF Bites:
WHERE end_date IS NOT NULL AND (end_date IS NULL OR end_date IS NOT NULL);
It's better than that! The definition of
end_date
isnull 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.
-
@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:
WHERE end_date IS NOT NULL AND (end_date IS NULL OR end_date IS NOT NULL);
You missed the best part:
SELECT null AS end_date
-
Good job, Sony.
-
@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 actualend_date
column being NULL in the table.
-
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.
-
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'.
-
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:
- FROM
- ON
- OUTER
- WHERE
- GROUP BY
- CUBE | ROLLUP
- HAVING
- SELECT
- DISTINCT
- ORDER BY
- 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.
-
As ever, the proof is in the eating
By contrast, SQL Server processes
⊠so you are right if it is SQL server and I am right if it is something else.
-
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 clauseNo, 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.)
-
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.
-
@scholrlea said in WTF Bites:
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.
It clearly left something...
-
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).
-
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.
-
@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.
-
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.
-
@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.
-
@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:
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.
-
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.
-
@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.
-
@pleegwat So what you want is generics. That would be the point where I pull out C++.
-
@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.
-
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:
- the highest priority super-fast interrupt handler on ARM (which has a lot of restrictions because most registers aren't saved on the stack),
- 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
- 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âŠ
-
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 astatic 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.
-
@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.
-
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. ;)
-
@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.
-
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.
-
@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.
-
@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!
-
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âŠ
-
-
@coldandtired I had a reply ready to post, but Microsoft moved it, and I can't find it anymore.
-
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.