- 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
Sometimes the good stories are in the narrative prose. It sets up the number of bad decisions, and sets up the WTF. Sometimes you get bad decisions that seem minor, but when piled up with all the other bad decisions, you end up with a bureaucratic nightmare that is all too common.
In other words, it doesn't have to be code to be a fuckup. The point of this site is not to show off bad code, but to illustrate "curious perversions in IT". Often that is bad management.
Admin
I hate to open a language holy war, but I never understood this complaint about C++. I don't have a good sense of how exceptions are compiled (though I do know a little), but apart from them, I don't see much of anything the compiler does behind your back that you wouldn't have to do manually in C if you were to get the same result.
For instance, take the Linux kernel. I wrote a kernel module that replaced the I/O scheduler with a new one. What did I do to get it? I wrote a bunch of functions -- then filled in a struct of function pointers with them. Voilà! Manually-created vtable! So you can't say that the vtable's extra bloat.
The only place I see "bloat" is templates; and if you stick to C you either have to create a generic version (perhaps with void*s) and lose type safety or duplicate the code just like the C++ compiler does.
Admin
There's too many WTF's to list here. The biggest is trying to catch an Error and deal with it like it's a normal scenario (which is a HUGE faux pax). The second is casting an int to a char (which removes the possibility of it ever being negative), then comparing it to -1.
The solution, you ask?
public static String readStream(InputStream theStream) throws IOException {
// Who knows where the stream comes from.
// Just assume they'll want it closed when we're done with it
// It's rare that you'll ever need to use InputStream by itself.
// Wrap it in a more powerful/efficient class instead.
BufferedReader theReader = new BufferedReader(new InputStreamReader(theStream));
StringBuffer result = new StringBuffer();
String currentLine = null;
try {
while ((currentLine = theReader.readLine()) != null) {
result.append(currentLine);
result.append(System.getProperty("line.separator"));
}
} catch(IOException ioe) {
// Log an error
// rethrow this exception (or some other Exception, if you prefer)
throw ioe;
} finally {
theStream.close();
}
return result.toString();
}
Admin
Wow. Reading those nested if-elses is like watching a car crash frame-by-frame on <insert video device of choice>, waiting for the moment of impact. And the catch block is priceless. The reply from support is correct, if you trim it a bit: "We are unable to ... code."
Admin
I too fail to understand how two WTFs per day, one of which is code and one not, is not a big improvement on one WTF per day which may or may not be code. Now there's guaranteed to be something for all types of WTFers!
Is it me, or is "InputStream theStream" a WTF in its own right? I mean, you get told off for writing "InputStream is, BufferedReader r", but at least that's short and useless. I know this 'theXxx' nonsense is all over the official Java pages, but I still hate it.
I think the original code is trying to just read the HTTP header, whereas this 'solution' post above me reads the whole contents of the stream. Thus what is required is:
Admin
Well maybe hirred, but definitely not hired (if that is any indication of what your resume looks like).
Admin
Yes, this solution looks better than the previous one. The fact that they are looking for a /r/n/r/n stop signal is important imo.
Admin
Actually, they are running out of heap because most of their break conditions of "_ch == -1" will never be true and the while statement can easily loop forever. As I read it, their only hope of exit is if they happen to catch a new-line character ('\n') on the 4th input read per loop iteration.
Another WTF is that, even if the -1 test was possible, they are appending this value to the buffer BEFORE they check to see if it's -1 (i.e. what they think will indictate an end-of-stream).
Admin
"Being a little worried about having to support their product without the source code for the HTTP client, they asked for a source code license."
Sounds a bit control freaky to me. If you don't trust the vendor, don't buy the code from them open or otherwise. The only time I even make an issue of buying source code is when the functionality is very niche specific, and has not been implemented 5,000 other times by companies I can fall back on if the one I am buying from blinks out of existence. HTTP clients do not fit that bill.
Admin
FWIW, I believe you are correct - I do not think that there is much behind your back-ness going on in C++. The compiler generates the code it has to in order to get the job done. Your example of an old-schoold vtbl is a perfect example - the compiler may be creating, adding and maintaining a vtbl for you in C++, but that is what you get when you use the word <font color="#3300ff" face="courier new,courier">virtual</font>. Much of the problem is not understanding what code, or how much code, it takes to do what you ask for. (Hell, is that not the underlying cause of most bugs - the compiler doing exactly what you asked it to! :))
However, in all fairness, earlier versions of C++ compilers (which were basically pre-processors that translated C++ into C and then fed it to a C compiler) did not always generate the best code, but they are pretty good today (IMHO), and there are C++-specific optimizations that are now taken advantage of.
Peace!
Admin
Actually had this happen on a project I was working on once (I wasn't working on that part). The solution ended up being to initialise the buffer to a size large enough to deal with what we were doing. Something like
new StringBuffer (10000) or something (Haven't worked Java for a while).
Rich
Admin
Yes, I learn so much!
Admin
"This one goes to 110".
Rich
Admin
I can do this one better. I worked for a long time for a company that modified another company's application for specific customers. The source code was old K&R style C code and was...not good.
One day, I found the following line:
process;
Clearly, this referred to the "process()" function that was defined elsewhere in the file. I emailed our contact at the owners of the source suggesting that the line probably ought to be removed. I got a similar answer. ("Please show us where it's failing".)
Admin
My thoughts exactly. Nothing wrong with a bit of constructive criticism, but lets cut the whining.
It does however give an interesting light into the mentality of some programmers (unless of course it is just one programmer posting under various names) who think that IT is really just programming and nothing else counts. Hell, IT is requirements analysis, specification, design, coding, testing, documentation, line management, project management, support, sys admin, DB admin, hardware design, hardware construction, hardware maintenance, hosting, security, sales, purchasing, etc, etc ... ... ... and they ALL have their WTFs. And if anyone's interest is exclusively restricted to one of those then that is a WTF of its own.
Admin
IIRC an OOME is only thrown after the JVM runs out of memory, runs the garbage collector to free up what it can, and STILL doesn't have enough memory. So when you OOME you REALLY OOME.
Admin
The code does not strip anything as the characters read are already added to the buffer and when the eol characters are encountered the special case is just to read more which it would do anyway thanks to the while (true). So indeed the whole if statement is broken. The int->char conversion is too. The -1 comparison is really really broken, but the casting also assumes that the characters stem from the first unicode plane. Something which is unlikely to be true for anything but the ascii characters as there are no encodings that correspond to the plane.
Admin
I cannot believe that people are taking this guy to task for saying that he doesn't need to worry about the syntax of a language he isn't using. That makes as much sense as if I were to call you ignorant or unqualified for not knowing the finer points of Haskell or Erlang, when you are a C# programmer. A lot of people apparently come to this site just to insult people they don't know. Your remarks say a lot more about you than they do about him.
As a Java programmer, I just want to confirm that a) variables declared inside a loop will actually just be allocated once, at the method level, and b) that comparing (char)-1 with -1 will not work. This code:
char c = (char)-1;
if (c == -1) { ...
Generates this bytecode:
0: ldc #2; //int 65535
2: istore_1
3: iload_1
4: iconst_m1
5: if_icmpne 15
In pseudo-code: load 65535 (or, (char)-1) on the stack, and store it in c, then load c and negative one onto the stack, and compare them and branch. Where negative one here is 0xFFFFFFFF. So it is comparing 0xFFFF with 0xFFFFFFFF, which fails.
(And, yes, the store to slot 1 is followed by a load from slot 1. javac doesn't optimize that, but the JIT will.)
A few other random remarks in response to other comments in this thread:
Looking for \r\n using line.separator is wrong because HTTP uses network line endings, so we actually don't want to be platform-specific. (Network, not "Win line ends" as someone wrote, although they happen to be the same.)
I don't think the InputStream theStream is a Java convention. I actually haven't seen much of that in Java code, it's usually InputStream is. theStream and aString and anObject I believe was a Smalltalk convention, originally.
What I don't like about C++ is not the vtables, but more the copy ctors and operator overloading. It introduces non-locality into the code. I don't like to look at a line like "a = b;" or "a = b + c;" and think that it can't be a performance bottleneck, only to find out later that in the "a = b;" case a copy ctor is called that allocates tons of memory, or in the "a = b + c;" case operator+ has been overloaded to represent a O(n^2) graph traversal algo.
If they had to be written as "a = b.deepCopy();" or "a = b.minPathTo(c);" then at least I would know just at a glance that there was more code I needed to go look at to understand what is going on.
Lastly, I must admit I have tried to catch OOM before. I think it's wrong to say that it can't work. First, the VM may not make any guarantees, but they're being conservative. Second, if you catch the OOM several levels up the call tree then a number of stack frames will have already been unwound by the time you catch it, which means the GC may very well be able to free memory that it couldn't before because some references that were live then are no longer reachable now. And, finally, I only caught it to log something, and then immediately rethrew it. Even then, it didn't work reliably, but I'd like to know if what I was trying to do was really so wrong in principle. Was it?
Admin
If I paid for source code and discovered that the comments were stripped out, then I'd insist on my money back under the logic that I wasn't delivered the full product that I asked for. The point of the source code is so that you can fix bugs, integrate it, and may be add some features; and you can't do that very well without the comments.
The Real Time OS that I use comes with source code from the vendor, and I spend a lot of time patching it (I'm continually amazed that people charge that much money for something so badly written). I also spend a lot of time trying to explain to their developers what the bugs are and how to fix them. It's extremely disheartening to have to train an RTOS vendor's support engineer on what a deadlock is.
My coworker who works on a digital signal processor chip wandered into my cube and idly asked what I was working on. I told him I was fixing bugs in the OS. He seemed surprised that I had the source code, and I replied "I need to have the source code, otherwise I can't get it to work." He then wandered off and mumbled to himself "I need source code too, I wish I had source code..."
Admin
I think the problem here is that there's a layer of support between you and the actual developer who may have an interest in cleaning up the code. The support people have a queue of problems to deal with, and their main interest is in shrinking that queue as fast as possible. If they had to actually escalate the problem, hunt down the appropriate developer, test the fixes, etc, they'd be ignoring the other problems in the queue. Their job is often to be a filter.
When opening a service request, there is never a category of "here's a suggestion of things you might want to consider before your next release." Instead the categories tend to be "critical - production stopped"; "high - experiencing downtime"; "low - occasional problems".
Admin
No it won't. char is 16 bit unsigned in Java, so the MSB is never treated as sign bit and the check always fails. There is a reason why the return type of all such read()-methods is int, not char...
Admin
I don't much understand this argument either.
First, I don't buy that you can understand code without having an idea as to the types of variables. If you see a.add(b), you can't tell me anything about what it's doing other than it has something to do with adding. If I tell you that a is a complex number, then you can guess it's doing math. If I tell you that a is a container, then you can guess it's adding b to the containter. Same with a+b. Just because you can't look at that statement and know exactly what it does doesn't mean that it's any worse than a.add(b).
As for "but you can put arbitrary complexity into a + sign", well, yes. But you can also put arbitrary complexity into an "add" method. And I doubt that if Java has an equavalent to, say, C++'s valarray, it would be called possiblySlowAdd(), or addInTimeLinearToSize(). It'd almost certainly be just add(). So now "add" methods have the same problem that you can't tell the complexity at a glance. Should we prohibit method names of add?
Personally, I'd rather have the syntactic sugar that operator overloading gives you than the obfuscation that you have to deal with without it.
Admin
And optimizing algorithms can change from one version to the next.
When I first encountered interpreted and compiled-but-virtual languages, I didn't like them because I was a further step removed from the processor and felt uncomfortable not being able to control the processor properly. But those sorts of things crop up in other places too. I was used to programming in C and it is relatively easy to know how that is going to compile. Use C++ though, and the preprocessor is doing loads behind your back and bloating your code for you.
I thought about it and realised that if I wanted to be a complete control freak then I would really have to program in assembler because even in plain C, the optimiser can be doing strange things behind your back. Useful, but still strange. And also, even in assembler, you need to know your CPU inside-out to know what it's doing because CPUs contain various levels of microcode and nanocode for various instructions.
I'll give you that one..
Understanding the CPU the registers and the communication between them can make you help right 'more efficient' programs, it doesn't make you write less bug free.
Admin
Can someone please banish the term "the real WTF"?
Admin
Have to agree with what the other guy said in response to this. a + b is just as immediately impenetrable as a.add(b).
But specifically with regard to copy constructors, assignment operators and the like, they are pretty important. They keep the OO model intact. If you create a non-trivial class then need to do a myclass1 = myclass2, you have no options. First instinct is to write all the copy code in place (eg: replace myclass1 = myclass2 with myclass1.a = myclass2.a, myclass1.b = myclass2.b etc). But that then means you're duplicating masses of code all over the place, not good when you update the class members etc. Okay, so you move all the copy code into a function of its own. But if you're doing that, why keep it external to the class? Especially if private/public is being used correctly.
I honestly don't see a reasonable alternative to copy constructors, assignment operators, equality etc etc. I also think your examples might be a little false. If you're coding an assignment operator and it requires huge chunks of mem for some reason, that's just a plain and simple fact. Whether you put the code in an overload in the class or put it inline it will still need the same code. As for operators that are doing something way outside the general understanding of common use (eg: the + operator creating a 3d rotating pie chart or whatever), that's just bad coding practice.
If you know C++ you know classes can overload operators. If you're looking at code, you know you're looking at a class instance. It's not a big leap to check the class implementation to see whats going on (especially with modern IDE's).
Admin
Output:
Test 1: FAILED
Test 2: FAILED
Admin
Anonymous wrote:
OOME is much worse than a failed call to malloc. The VM spec states
that after an error is thrown everything may be broken and all guarantees the lang and VM gave you may be long gone. In Azureus they do catch and report errors, probably with a catch(Throwable) line: I got an OOME and after that every action I tried to do involving a torrent threw an AbstractMethodError because the VM invalidate part of the class. Never catch an Error in Java.
WTF? Never catch OOME? If you do not catch Errors in Java the JVM will just print a stacktrace to the prompt and continue running.
You need to handle OOME in some way and that is likely to include restarting the JVM. What Azereus should have done is to catch the OOME, report it if possible, and then restart the JVM.
It is true that you shouldn't normally catch Errors in Java. But you need to do it a few central places in order to report it and restart the JVM. It is much simpler in JDK 5.0 where you can register a default error handler on all threads.
Admin
Despite all the glaringly obvious WTF:s that so many already have bashed (catching OOME etc), I'd like to point out a few things that would still be wrong, had the author managed to avoid endlessly allocating more memory:
1. What does the function return? The WTF snippet is actually part of a larger method - as demonstrated by the unterminated while-loop on top: while (!_validConnection) - but let's refactor this in our minds to a getHeader method, returning either the StringBuffer or a String created from it. What would the string buffer contain after completing the loop?
Answer: All characters up to *but not including* the final \n of the double-CR-LF. I.e. something like this: s/^\(.*?\r\n\r\)\n.*$/\1/ in sed syntax
2. Is this being run on a socket input stream? Then what happens to any data that's come in after stream.available() is called? Unfortunately, when parsing a line-based protocol from a socket, you'll need to either a) read byte for byte until you've read an entire line, or b) maintain a per-socket state-machine and update it with incoming data. Unless you "can" assume that your N-byte (where N is probably just set to stream.available()) buffer just so happens to contain the new-line (or double-newline in this case). And by "can" I mean that you can't.
Oh, and here's a simpler way to write this WTF:
<font> </font>Let's try that again with more up-beat comments!
(Never mind that InputStreams on sockets, files and stdin can behave quite differently, and that all the comments are more or less false :P)
Admin
I just love WTFish comments to WTFish code. 0xFFFF in an unsigned data type is 65535, and not -1. Ever. Also, as has been mentioned, the char is promoted to an int, and promotion always preserves value if possible. Since 65535 can be expressed as a Java int just fine (0x0000FFFF), this is what it gets promoted to. And this never has, and never will, be considered equal to -1 (0xFFFFFFFF).
Admin
Yes, you get my remark wrong. The "char _char" statement pushes a byte onto the stack. In other words, the variable name "_char" is stored in the part of memory called the "stack" as opposed to the part called the "heap".
The person I was replying to implied that each iteration of the loop would use extra memory, I was saying it would reuse the same memory because its the stack... I didnt say anything about the "loop generating a stack" mr assumption man.
Admin
Yeah, theres actually plenty of good open source HTTP clients they could have used.
One case where we had to do the same thing was being told to release our Unreal Engine game on the PS2 - the Unreal engine isnt designed for PS2 and only one company has ever bothered to port it to that platform. So we bought their ported engine and it was buggy as hell, so we had to buy the source so we could fix it...
Admin
in Java char is signed as are all primitives
Admin
My 0.02,
I think the real WTF is everyone thinking this is the actual code snippet with no anonymizing at all. My vote is that the true HTTP-client code was possibly written in VB -- though not a wtf itself, I'm sure whoever wrote the code knew not what they were doing (think: Not using IE but starting with Form and WinSock control). :)
Captcha is "vblover"
Admin
Personally, I like both the stories AND the code samples. Sometimes the code samples are too convoluted for me to parse quickly... and I sometimes don't have lots of spare time to parse the code here.
Maybe those who don't like the stories are remembering early school days with math problems embedded in stories... A train leaves Chicago at 4:00 PM, traveling at an average speed of 50 MPH. Another train leaves Denver at 6:00 PM, traveling at an average speed of 60 MPH. How many blue cars does the train that is going downhill have?
Admin
while (!_validConnection) {
StringBuffer _stringBuffer = new StringBuffer();
try {
while ((char _char = _inputStream.read()) != -1) {
if (_char == '\n'){
if (_stringBuffer.charAt(_stringBuffer.length() - 1) == '\r')
_stringBuffer.deleteCharAt((_stringBuffer.length() - 1);
// Do what ever you need to do to the line
break;
}else if (_char == -1)
break;
_stringBuffer.append(_char)
}
} catch (OutOfMemoryError error) {
// received a bad response, try it again!
continue;
}
Admin
almost forgot. to say why I posted that... The above is a much better version of the code
Admin
you are either really bored, or you wrote the offending code in the OP and are feeling guilty?
Admin
Nah just board,
Admin
http://thedailywtf.com/forums/12/ShowForum.aspx?PageIndex=26
Admin
I knew a guy named Brendan who was often bored and wrote snarky comments in code to pass the time. :)
Admin
Really? Well if that is so, you should definitely go and tell Sun, because they got it all wrong. Alternatively, just shut your airhole.
Admin
"We are unable to see any problems in the code, please supply a test case" - fair enough, the code worked for a long time. What they had to be asking for is the exact sequence the error can be replicated. The error scenario, I suppose.
The code is dizzying, though.
Admin
I found your advertisement on our site.
You should know that I recommend everyone who visits and asks about you not to purchase anything from someone who has to revert to stealing space from an environmental group as broke as we are. Anyone who would revert to such sleazy attempts to get free ads are probably selling stolen or worthless products.
Advertise all you want but I have labeled you as a sleaze ball who is unreliable and of the lowest order of business people.
On the other hand, I appreciate that you think we are so highly visible as to steal our space for your worthless ramblings.
John L. Wathen, Hurricane Creekkeeper
Creekkeeper is a member of Waterkeeper Alliance
Who has the authority to say someone else is not being a good steward of the environment?
Anyone who notices John L. Wathen, Hurricane Creekkeeper Friends of Hurricane Creek Who has the authority to say someone else is not being a good steward of the environment?
Anyone who notices
Admin
tzkwbm webq oamhyxwv yqzrp wkdybumg bnsqhfcwy fvts
Admin
tzkwbm webq oamhyxwv yqzrp wkdybumg bnsqhfcwy fvts
Admin
ioah lnvcyszbr dqnia fjbcr lxqyvb gcvw arbpnyewz
Admin
vctpeg aqixbl zswt ydzjhk wavrxjum xsgzbhmku cvbfmlpyd
Admin
rczmb qrfczoh lqarz idrap vwez kzaifgstu xlwyscbtz
Admin
jfkoibvzt nrvumbhlo bdxtrlmce tngpahe mxaih wbntoupjv dwqhaykuf
Admin
djevxb zjbm enyqwvfrz ylgtej sztfk quckvzng fwmjdhct