- Feature Articles
- CodeSOD
- Error'd
-
Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
It IS a WTF, because it doesn't handle FILE_NOT_FOUND!
Admin
TRWTF is writing
==FALSEinstead of!Admin
Makes you wonder why they don't return the error code in the first place instead of storing the error somewhere (very likely in some global variable) and returning a BOOL (which in C-land is just an int).
Admin
Is the long-time developer's name Paula?
Admin
good one
Admin
The GetLastError() is a giveaway that this is most likely a Windows API call, which uses the "return false and check GetLastError() afterwards" convention a lot. Fortunately GetLastError() it's thread-safe.
Note that Unix / Linux also follow this convention a lot. There's the (thread) global errno variable that serves the same purpose as GetLastError().
Admin
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
-- nickm_tor, apparently
Admin
For me in C it feels quite common to do it like that.
In Unix/Linux development there is
errno, on Windows we gotGetLasterror.I'm not saying it's the right thing to do but it's definitely a common idiom: If you don't need details about the error, your code will have nothing to do with the details of the error...
Admin
Unless I'm misreading it because it's still early in the morning (a.k.a. before noon), this is definitely a WTF. If there isn't an error, it handles the error. Or the value of
erroris the opposite of what the variable name means.Admin
They handle an error if the error flag is FALSE?!
Admin
This feels even more screwy because if you started with "functions return an int, 0 is success, anything else a failure denoted by the value (or you need to look in errno)", and factor in that int 0 is falsey, and any other value truthy, then surely the error case would be "error == TRUE" ?
Admin
Well, they call the variable
error, but it's reallyresultor honestlysuccess. It's a badly named variable, not a full on backwards logic.Admin
Then the "annoying" convention and the "standard" convention are the same, except that the annoying convention names the variable the exact opposite of what the value means?
Sure, we've seen worse, and we've seen this one many times, but it's definitely a WTF.
Admin
That comes from the very early days. Returning an int pushes 4 bytes onto the stack, and most of the time you only care about success. Those four bytes in every function call on the stack add up quickly, and if you only have 16kb of memory total it's vitally important you save as much memory as possible. To that end, the error number is a global, and we use a single byte that's either 0 or 1 to indicate if you need to check it. Now every function call that needs to care about errors only adds 1 byte to the stack, not 4.
Now however there's no reason it needs to be used, we can afford to lose 3 extra bytes for each function call that might return an error, but we don't because the standard for how it works has been written and changing things risks breaking things.
Admin
I absolutely would do this. Note that BOOL is not the built in Boolean type. I would not treat it as such.
Admin
Having been a C dev a long time ago I can explain some of the history behind this. C doesn't have a built-in bool type, so it's often #define'd as FALSE = 0 and TRUE = 1 (including in the Windows headers). But in C, anything nonzero is considered true, so it's more correct to say TRUE = !FALSE.
That led to a general rule of never explicitly checking for TRUE. Many overly-zealous devs took that and ran with it, mandating that any "bool" check tested FALSE instead. So it's no big surprise that a long-time developer in a long-running C project would be of that school.
Admin
"OK, function, do your thing and give me the error (eye roll). Oh, no error (eye roll)? Let me go ahead and check the error anyway (eye roll)!" Now all the code needs is the correct contents of the function so that it can do it right itself in the (non-)error-handling section.
Admin
Much better to include
<stdbool.h>and use abool, which is not just anint, and which has "proper" boolean-type semantics, notably squashing all "true" values totrue, like in C++.Admin
Yes, that would annoy me too.
Admin
When success is error, and error is success, then everything is possible!
Admin
No, the standard is:
int error = someFunc(); // error=0 is no error if (error) {// handle whichever error occured
There is only exactly one possible "success", there are an infinite possible "failures", so you map your returns that way, the one to one, and the many to many.
Admin
S_FALSEis knocking on your door, asking you what you mean by "exactly one" success.For the benightedly ignorant (or just unaware, whatevs) among the audience,
S_FALSEis a "successful" return from calls to COM APIs in Windows, indicating success with a nuance. Its value, unlikeS_OK's zero, is one.Yes, you heard me right,
S_FALSE == 1.Admin
You can return 0 on error, Then you call it
BOOL success = some_func(); if (success == false) { // Handle error }
That's the same semantics as the code, except the misleading variable is renamed.
Admin
Ah, yes. The classic case of 'Yes, there is no error'. I had a few discussions with co-workers about that one.
Thankfully I've always managed to sway them.
Admin
Honestly, this looks like someone came into the project fresh off doing assembly and decided to reimplement the error flag. They just did it kind of wrongly. But I definitively have seen stuff like this back in the day when people were still getting used to C. And it didn't go away either.
Admin
Ok, I had to brush up a bit on assembly since it's been decades. And TLDR I got things backwards. I was thinking off the flags register. I think. Apparently my memories of what I did in the 90's aren't as sharp as they used to be.
Admin
In ye olden tymes upon thy IBM maynframeth, return codes (RCs) allowed a "strange" way of identifying several degress of success: While RC=0 obviously meant "everything okay, operation succeeded as expected", non-zero codes could still mean success, but with limitations or explanation, like RC=2 for "operation completed due to override", RC=4 for "operation completed with minor errors", RC=6 for "operation completed, but not as expected", up to RC=255 for "operation could not be performed, severe error". This of course depended on the actual system and problem programs, as well as how user programs were written. Additional reason codes, like UNIX's errno, could reveal further details that the programmer could query. And obviously, documentation was key - so you had to implement your program flow and JCL accordingly in order to avoid repeating or restarting job steps for something that was "sufficiently successful" for your specific task... yes, I am old... and i'm not sure I remember this entirely correctly...
Admin
Somehow I don't get the examples. Shouldn't the functions return 0 on success and non-zero (often -1) for errors? So shouldn't the pattern be the following?
Regarding the original submission, I also think that it is a RWTF, because the name of the variable does not relate well to the condition in the if. You test for "error" being false and then do error handling? Wait! what? That is totally confusing.
success == falseorerror == truewould make much more sense.Admin
You don't have to reach that far back. I've seen stuff like that as recently as today. Just look at the Metatrader API. And yes, that Metatrader. The company that runs the largest Forex retail platforms. Their entire scripting language, and from what I've seen their server plugin API as well runs on the pattern of returning an integer result code that you than match against an enum and if the numbers match one of values that mean error you query GetLastError() to see what actually happened.
Admin
The fact that "other developers follow" says as much about them as it does the "long term developer"...
Admin
Rule one of working on any project is that you always follow the patterns and conventions laid out by said project.
The only thing that sucks more than having a bad set of those (which may or may not have been good ages ago) is having a multiple of competing standards where each part of the project does things its own way.
If something is done wrong, but consistently wrong you can at least learn and understand "the way". If different parts of the codebase all do things their own way than you can't even do that.
Which is why there is a special place in hell reserved for people that break with conventions.
Admin
There are clear conventions with COM coding, at least, and things are very readable as long as you follow them. If you don't care about a specific
HRESULTlikeS_FALSEthen just use theSUCCEEDEDmacro, and then you don't need to worry about the details of how the bits are assigned in a properHRESULT.Possibly TRWTF is that I like the COM result conventions enough that I've used them in non-COM code.