- 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
That sad thing is that this code:
Could be fixed by just using
std::map
:https://ideone.com/7RZoWI
This sort of thing is why I believe
std::vector
andstd::map
(and other standard containers) should be taught before ever even mentioning plain arrays.Admin
I see nothing in the original code to suggest this is C++; it looks like vanilla C to me. It is certainly possible to implement a hashmap in plain C, and it's something a lower-division student learns (even as an EE student, Data Structures was a required CS class); it's just not neatly prepackaged for you.
Admin
it is literally the second sentence.
Admin
:headdesk: Indeed it is. Mea culpa. I didn't go back and reread the narrative part of the article, I just looked at the code. And now that I look at it yet again, I see the
bool
data type. Absolutely nothing else looks C++-ish, though;char *
,strcmp
,strcpy
— C++ only by virtue of its backward compatibility with C.Admin
A bonus point in WTF for allocating dynamic memory just to release it afterward. In case a branch of the second switch is missed, the search will be performed with something that is not nullptr, but pointing anywhere (it might segfault, or in multithreaded environment it might have been reallocated by the time the pointer is used.)
Lovely.
Admin
I don't know. If the rate of errors is high and the number of messages is large std::map's operator[] and find are advertised as O(log(n)) in time complexity. Maybe it's better to use std::hash which is O(1). If the error rate is not all that high and there are only a few 100s of messages then you have to wonder how worthwhile it is to optimize the search... could just use std::find on an std::vector<std::pair<std::string, std::string>> and pay the (O(n)) cost.
<!-- Easy Reader version: who cares about the performance of a low probability edge case? -->
Admin
If you ever give me a language without a Map type, it will be the first thing I write in that language. I'm a stringly typed guy.
Admin
In this case n is fixed, so O(log(n)) = O(1). Please don't abuse asymptotic complexity.
In practice, it might well be the case that the cost of hashing the key is more than the few lookups done by a dichotomic search.
Admin
delete[] isn't in C, is it?
Admin
Yeah, we all love UB. Well, until the code has to be ported to a DS9000, at which point someone (or more likely a million someones) dies in a nuclear fireball.
I guess it's the "well, I have to initialise this pointer to point to something" thing, except that he hasn't heard of either NULL or nullptr, so he grabs a pointer from the only place he knows, the heap.
I've seen enough fallout from UB to refuse to sign off on a code review if I find any, from
*bp++ = expression_with_star_bp;
in C toprintf("%s\n", non_pod_object_by_value);
in C++ (both of which I've seen) and more. (The second example is UB if the object is not a POD, and maybe - don't remember - if it is a POD. Version 6 of the Sun Solaris compiler passed the address of the object, while version 8 passed it by value and barfed warnings about it. The chuckleheads who wrote that code had to backpedal and rewrite it to do something sane.)Admin
:wtf:
Admin
That's about the silliest thing I've read today.
Admin
Admin
The article says "...it couldn’t do anything about other than cough up an error and quit". If that error description lookup happens only before quitting, why optimize it? OK the code is ugly and hard to maintain, and spends say 10 ms instead of 1. How much developer's time it's worth to spend on 9ms improvement? Is it algo trading industry?
Admin
Talk about premature optimisation.
If your code has a fatal error often enough that a linear search of an array containing a few thousand strings is a performance concern, then you have bigger problems than your search strategy.
In the context of big-Oh O(n) or O(log n), then 2600 elements is not exactly a huge number and there's no guarantee an asymptotically-faster algorithm will be faster.
A routine that takes n iterations, will be faster than on that takes 1000 log2(n), whenever log(n)/n > 1/1000 -- so about 15000 elements. With memory latencies and cache misses, those relative timings are by no means unreasonable with a data structure like a map that stores the data with a bunch of non-contiguous heap allocations.
Admin
Yeah, this is a heavy case of why bother to optimize. The only thing you reasonably want to optimize here is the amount of boilerplate code.
Admin
Done in Java because I'm not up on C++ and I don't want to learn it for a stupid joke.
...runs away laughing
maniacallyevilly.Admin
I love C. It's simple, straightforward, fast, and sometimes even more elegant than equivalent C++, for short and sweet algorithms. But even I know that bodging a bunch of C into the middle of a C++ app isn't going to do anything but engender hate and loathing. I wish more people knew when to stick with what they like, and when to branch out.
Admin
Or a first-year CS teacher's solution. Some people apparently think
break
statements are as evil and non-kosher asgoto
s.Admin
Am I the only one to see this... and think: Every time something gets changed means a recompile.
Would't it be better to put the error codes in some kind of lightweight text file? Simple database? That way you can add codes and update descriptions without having to recompile?
You could even use XML and make it enterprise-y.
Admin
The sad thing is that in C++
goto
isn't that evil because unlike Java there is no labeled break or continue, so you need it to replace that functionality. IIRC there are no plans to add labeled break or continue to C++.Admin
FTFY :trophy:
Admin
First, a WTF in the article:
This isn't a two dimensional array. This is a one dimensional array of ERROR_REC objects. Which probably are some kind of (const char*, const char*) pairs.
The next :wtf: is why would you split this into 26 different arrays? Ok, the mapping from name to description has to be written down somewhere (although maybe as suggested above it could be in a file instead of in code). But you can just have one big table and then do the search there.
The biggest head-banger, though, is that horrible search function. This is something that should be a couple lines long (mostly depending on how you stored the descriptions). If all you had was an unsorted array, for example, you just do:
Admin
What is wrong with having an error message like
"AA01: Error AA01 Description"
? No need to have any hashmap when application is about to quit anyways! If there is an error which:Maybe it is time to quit quickly! What if that error is because of low memory, and additional memory allocation will result in OOM, that will silently quit defeating the whole purpose of having an error message to begin with.
What? let the poor application die in peace quickly.Admin
Although the fact that the error code is a string itself seems weird to me, I would have expected a number.
Admin
Good point, yes during initialization makes sense, that also could be used for i18n.
Admin
bool
is in C; 7.18 Boolean type and values<stdbool.h>
. Of course, most places that use C continue to act like it's still the 80's.I also like how
ret_desc
isn't declared within the function, meaning that it's almost certainly namespace scoped with static lifetime, unless it's declaredthread_local
hahaha of course it isn't. Hope you didn't want to get the description of more than one error message, or report on errors from two threads at the same time!Admin
So, "Error QB57 Description" made them happy? One stupidity deserves another.
Admin
Presumably the descriptions were either placeholders or anonymized prior to the story being uploaded.
Admin
Huh. I guess 2*26 really is 62.
Filed under: Maybe you meant 2*26+10?
Admin
In this case, yes:
Admin
Filed under: Code not defensive enough, those edge cases need writing, Stat!
Admin
Indeed! Clearly, this coworker needs to at least include the codes for all printable characters in the Unicode standard.
Admin
Admin
I strongly doubt that'll compile.
Admin
Not exactly equal, but conceptually similar:
Produces:
Admin
Well, yes. But that doesn't include what is almost certainly a multibyte character literal where the compiler is expecting a single byte.
Admin
New version:
EDIT: Fixed the misquote. And then corrected the "fixed" misquote.
Admin
No, it isn't, nor is
new()
. It's an even worse mish-mash of C and C++ than I noticed at first.Filed under: You made me look at that terrible code again. I hate you.
Admin
I love the gcc take on passing non pods to ...
It compiles successfully but with a warning (and who takes notice of those - no one where I work for certain) that the code will crash at runtime.
That's possibly even sillier than playing tower of hanoi on an unknown pragma
Admin
Exactly what I thought. Would also make localization easier.
Admin
I'm pretty sure that was redaction for the article. Nevertheless, you have a point, because the user is probably going from "Error QB75" to something like "Error QB57 A participle is not permitted at this thingamajig point in the binary query tree."
But, hey, they'd better be happy: it shows them error messages now.
That could have solved the whole problem right there (output) :
"An error has occurred: error code QB57 ಠ_ಠ. Cause of the problem is ¯\_(ツ)_/¯."
There...be happy with that.
@Dreikin with apologies; wrote it before I saw your response.
Admin
Admin
Okay, I buttumed stuff and now I look like a butt. So? :stuck_out_tongue:
Admin
False.
http://dictionary.reference.com/browse/assume 1: to take for granted or without proof:
This implies without prior reference. However, in this case, information was internalized, analyzed, and applied into an interpretation, therefore it cannot be an assumption, as claims could certainly be sustained.
Filed under: Do I get my :badger: now? I try SO HARD but nobody seems to care!
Admin
I answered a point about the number of branches in the two switch statements, and you answered as if I was talking about the number of different alphanumeric characters. Sounds like you assumed something.
Admin
Okay, let's do some exploring then.
https://en.wikipedia.org/wiki/26_(number)
Relevant references relating to the article:
The number of letters in the basic Latin alphabet, if capital letters are not distinguished from lowercase letters.
Note that said switch statements branch off based on said characters of the Latin alphabet, therefore we can infer from the context that we are talking about letters.Furthermore, it is logical to infer from the array definitions above said switch statement that it would be possible to have numeric values in the error code, hence the simple test count for alphabet and numeric characters, of which the stated sum was equal to.
What portion of my assertions are not without proof? Did you (at any point) claim that you were in fact talking solely about the number of branches in the two switch statements? Did you ever specify that you were indeed NOT talking about interpretations of ways that the number 62 could have been derived from 2*26?
Filed under: I think not! Also Filed under: However, you are free to assume any opinion of my thoughts and words. @Blakeyrat any thoughts?
Admin
I did think of that possibility, but I wouldn't take it for granted. The universally accepted definition of a customer is "a moron who pays you some money." I wouldn't be surprised at all if a customer asks to replace "Error: QB57" with "Error QB57 Description" because it is more ... uhm, descriptive.
That apart, even if the actual error was redacted, I wouldn't give the submitter the moral high ground, until I can see what the actual message was. It could well be that the submitter thought "Error: can't insert that thing into this thing" would be a useful error message. Nobody should have the right to share other people's poor code as WTF, unless they can prove that they are not TRWTF themselves to begin with.
Admin
Yes, I was particularly taken with the ingenious use of new() immediately followed by delete[], as alluded to by @Jerome_Grimbert.
Also, typo in Remy's easy reader version (cut and pasted 26 times, of course):
Admin
A couple of words of wisdom are needed here:
"bsearch" and "qsort"
Look them up in a manual page nearest you. Oh, they are in the C standard library and should be available in the library.