rafterman's Journal
[Most Recent Entries]
[Calendar View]
[Friends]
Below are the 20 most recent journal entries recorded in
rafterman's LiveJournal:
[ << Previous 20 ]
| Monday, August 7th, 2006 | | 5:59 pm |
Welcome to Fortran
So I left my last job with all the evil code it had, and I thought I'd be able to put this blog out to pasture. Unfortunately I've now begun an honours thesis in physics, which involves working on code which goes above and beyond the evil I'd seen before. When I started on the project, one of my supervisors warned me that the code I'd be working on involved "thousands and thousands of lines of fortran". I shrugged this off without a care. How bad could it be? I've seen the worst code can get. Bring it on! Forty. Thousand. Lines. That's right, the code for this project which I got handed clocked in at just over 40,000 lines of code. After a lot of reading and piecing things together it became clear that most of this was either dead weight which is no longer actually used, or repeated code, because the author was too lazy to structure things properly. After a bunch of hacking I've brought the code down to around 10,000 lines which actually get used. After going through this process it was time to work out what the code actually does. Comments? None. Useful variable/function names? Don't be stupid. Indentation? Why bother. To give you a feel for what we're dealing with here, consider the following piece of code found in dfj3.f (obviously).
SUBROUTINE OBME(M1,M2)
N=M1
M1=M2
M2=N
RETURN
END
SUBROUTINE PORAD(I,N)
DIMENSION I(N)
K1=N-1
DO 1 K=1,K1
K2=K+1
DO 2 L=K2,N
IF(I(K)-I(L)) 2,2,3
3 CALL OBME(I(K),I(L))
2 CONTINUE
1 CONTINUE
RETURN
END
Usual rules apply. First person to tell me what this code does wins a shiny new donkey. Current Mood: busyCurrent Music: Radish - Little Pink Stars | | Tuesday, May 23rd, 2006 | | 9:58 am |
Arbitrary limits
So, this code uses a set of libraries written by the head monkey. All these libraries live in a single 12,500 line file. Since it's library code and there's a buttload of it, I havn't read most of it. Every now and then I poke my head in to check something out and every time I come away amazed. One of the things this library supports is memory mapping files. I dunno if you've ever done memory mapped files on windows, but it can be a bit of a bitch, so having a library wrap it all up neatly is a nice idea. Of course there are libraries out there which do this for you, are cross platform and have cleaner interfaces (e.g. boost) but let's not let that worry us. We have our library here so that's tops. The thing about this library is that it's just as poorly written as the rest of this guys code. In particular, there's an arbitrary limit of 10 memory mapped files which can be open at any given time. This is imposed by having a global array of structs containing the mapping info which has a fixed size of 10 (and yes, that's the number 10, not some number like MAX_MAPPED_FILES). Why would you do this? What's wrong with having dynamically allocated data structures? Why not let the operating system dictate how many mapped files it can deal with? And where did the number 10 come from? And this isn't the only place with magic, arbitrary numbers. As I'm sure I've mentioned before, there's the array module which reinvents vectors. Except these arrays have an arbitrary size limit of 2 million elements (After I bumped it up from 1 million). Again, why not let the operating system tell you when your data structure is too big? It's just plain crazy! Why are we still using these libraries you may ask? Because the code is too damn convoluted to refactor them out. A lot of progress has been made, so there's only a handful of places left using monkey mapping or idiot arrays, but the last few cases are the hard ones. The days of using this insano library are definitely numbered. Current Mood: busyCurrent Music: NOFX - Reeko | | Friday, May 19th, 2006 | | 10:12 am |
cute? evil? you decide
Today's interesting use of #defines is kinda special.
#define o_clock *60*60
So now you can do things like
int BreakfastTime = 8 o_clock;
and similar things. I can't decide if it's just kinda cute or if it's completely evil. If you read the #define before the code that uses it you know it's coming and it makes sense and makes the code easier to read. If you don't read the #define before the code then it makes absolutely no sense and confuses the living pants off you. So it's time for a straw poll. Is this cute or evil? vote in comments. Current Mood: contemplativeCurrent Music: Butterfly Effect - Crave | | Friday, May 5th, 2006 | | 2:36 pm |
clearS() strikes again
So in March of last year I ranted about the clearS macro and how it was pissing memory all over the floor. Well, it's back and causing more trouble. For those too lazy to scroll down the page, the macro is defined as #define clearS(S) memset(&S, 0, sizeof(S)) So before, the problem was that when this macro was called on objects with allocated memory, that memory would get leaked. I cleaned up all the places where this happened and left the macro there for the objects it was safe to use on because I was too lazy and too busy to fix it properly. Cut to a year later and I'm refactoring some classes to suck less hard. These classes all derive from a base class, and it turns out that they'd benefit from having a particular method, so I throw a pure virtual function into the base class, implement it in all the derived classes, bob's your uncle. Now, as you probably guessed, objects of these derived class have clearS called on them. The fun thing to notice here is that when you take sizeof() of an object in C++, it not only reports the size of the data members, but also gives you 4 bytes for each virtual function in the table. As a result, when you call clearS on an object which implements virtual functions, these function pointers get trashed and your program starts crashing in weird and wonderful ways. So once again, because a certain fucktard was too lazy to implement proper constructors for all his classes all those years ago, I'm cleaning up messes that should never have existed. How much fun is life. Current Mood: crankyCurrent Music: Ben Folds - Rocking the Suburbs | | Wednesday, February 1st, 2006 | | 5:09 pm |
OK, wrap your brain around this
OK, I thought the macro I found yesterday was bad. I was so very, very wrong. I've now found a macro which has a switch statement based on a local variable (eg, not a parameter of the macro). The case lines come in the forms of macros, which if matched, call a macro which conditionally returns, based on a function call which also is not a parameter to the macro. If none of the cases match in the top level macro, it returns another macro which also references a local (non-parameter) variable. Think about it. Current Mood: amazedCurrent Music: Gin Blossoms - Follow You Down | | 4:52 pm |
Am I missing something
Ok, in a number of places in this code I'm looking at I see stuff like
void foo(){
enum { x = 1 };
...
[a bunch of stuff, using x as a normal variable (though not changing its value]
}
Why the hell is there an enum in there? What is wrong with const int x = 1;? Am I missing something here or is this is stupid as it looks? Current Mood: confusedCurrent Music: The Wrights - Evie Part 3 | | Tuesday, January 31st, 2006 | | 2:34 pm |
A brand new form of evil
I've been working on this code for a few years now, but today I came across a brand spanking new piece of evil in the database code. This is code which I rarely if ever touch, but I've had to dive into it today to chase some bugs and I've found some pretty horrible stuff. First, a warm up question.
void f1() {
int x = 37;
f2(x);
}
void f2(int &x) {
int *p = &x;
}
What is the value of p? Is it the address of the reference x on the stack of f2 or is it the address of the int x on the stack of f1? The answer is obvious when you think about it, but not obvious at first glance I don't think. Also, why not just make f2 take a pointer to an integer and save everyone's eyeballs? non-const references make baby jesus cry. Now, for the big one. Return statements in macros. Yep, that's right, you heard me, a fucking return statement in a fucking macro! There the code is, happily trundling along, making things up as it goes, it pops off to what looks like a function call and then *BAM* suddenly jumps to the end of the function. After some head scratching you grep for the function call and lo and behold, it's a macro! And it has a return statement in it! Arg! And it's a conditional return, so it won't always return, it's not like it's some neat clean-up-at-end-of-function-and-return type macro. It's in the middle of the code, taking care of fucking program flow control. How the hell are you meant to debug this kinda shit? You can't put break points into it to see what's going on, you can't even obviously see what condition will make your function return without going back up to the macro, it's just a total cunt of a thing to deal with. Why do people do these things? What on earth could convince them to write such code? Is it like one day they woke up and thought "you know what, today I'm going to do something totally evil so that whoever has to deal with this code next gets the urge to slowly and painfully kill me". I should have become a gay hooker or something, at least I'd spend less time getting fucked in the arse then. Current Mood: annoyedCurrent Music: Some crap | | Tuesday, December 13th, 2005 | | 11:31 am |
So much anger
It's not even midday yet and I've already been subjected to 3 different pieces of code which make we want to stab myself repeatedly in the eyeballs. 1) Now, I'm not much into GUI programming, it's not really my thing, but even I know, if you want the user to be able to enter text, you give them a text box control dealie and that takes care of everything and when you want to know what the user typed in you just look at the contents of that box, simple. Not for stupid monkey man apparently. I just came across code which needed the user to be able to enter some text. "Aha!" you'd think, "time for a text box". But no, instead he has gone and implemented his own text box. For every key stroke it does a whole bunch of magic to make sure it's got it's cursor in the right place and is updating the string correctly and that everything stays nice and up to date. He's even implemented the part where, when the thing gets painted to the screen, he modifies the drawing routine to insert a cursor at the right place! All this in only 200 lines of code! Awesome. Why write 1 line of code to call a library when you can write a whole new class yourself!!!! 2) C++ code is known for being full of memory leaks and stuff, and this is usually because a) people are stupid and b) they don't have a consistent set of rules for doing their memory management. So I'm reading through some code here and I realise there's a whole bunch of things are being newed but but not deleted. I go through and stick in the deletes as appropriate and run the code. Lo and behold the system freaks out when I call delete on these objects. I investigate further and to my shock, horror and disgust, in the last method that was called on these objects, there is the code
delete this;
That's right, these objects delete themselves! Wow, what a good idea, now we never have to worry about these things not getting cleaned up! UNLESS THE FUCKING CLEANUP FUCKING METHOD DOESN"T GET CALLED. What kind of a horrible cunt hides a delete this deep in some random method in the vain hope that that's going to be the last method called on the object. It's just completely fucking insane! It such an ass backwards way of doing things it's not funny. Not to mention that if you ever happen to create on of these objects on the stack and then call the magic method the whole thing will completely fucking shit itself. What kind of a brain dead moron writes this kinda crap? 3) I'll tell you what kind of moron: the same kind that implements menu callbacks by associating each menu item with a keystroke and then when a menu item is called, it works out a keystroke and then calls over to god dammed keystroke handler!!! This just makes no fucking sense. The amount of anger which this causes is just beyond belief. How does someone come up with such a system? What could possibly inspire such a design? I can't believe there is still so much evil left in this code which I havn't found yet Current Mood: angry | | Monday, November 14th, 2005 | | 4:40 pm |
Again with the standards
So, if there's one thing that shit me more than ID (don't get me started) it's code/systems which don't comply with standards. More importantly, when they don't comply with standards no NO GOOD FUCKING REASON! Two examples spring to mind: 1) The code at work which reads the raw data files is implemented in such a way that it can only deal with a particularly restrictive subset of the file format specification. As such, we've had to make sure that all the data we get in conforms to that subset. SO when someone accidently sends us data which isn't part of the subset, we're fucked! How retarded is that? It's not like it's a particularly difficult file format either, it's just that the guy who wrote it was a lazy prick who couldn't be arsed doing it properly. As such I've had to rewrite the entire thing, which is good, since the code no longer sucks, but sucks because I've got much better shit to be doing than rewriting code that should've have been done right the first time. 2) Borland C++ builder is a filthy whore of a system who, apart from crashing on a daily basis, doesn't put its fucking headers in the right place, so if you want to write portable code (heaven forbid) you have to litter your code with shit like
#ifdef MORON_COMPILER
[do things the broken borland way]
#else
[do things the right way]
#endif
which is fucking ugly and annoying to read. How fucking hard can it be to have your fucking headers in the right fucking places??? Fuck! Current Mood: annoyedCurrent Music: The Darkness - Get Your Hands Off My Woman | | Tuesday, August 16th, 2005 | | 1:07 pm |
Awesome structure
I just came across a handful of functions which are nicely arranged throughout the code. For each of these functions, their prototype lives in foo.h, their implementation lives in bar.c and they each get called in one single place: baz.c. And people wonder why it's so hard to find your way around this code. Current Mood: cynicalCurrent Music: The Selecter - Three Minute Hero | | Tuesday, August 2nd, 2005 | | 2:49 pm |
Fucking morons
Fuck I hate morons. A shiny new donkey to anyone who can tell me how many times this loop runs through without actively thinking (even a little bit).
for(int i=n; --i >= 0; ){
[do stuff (not using i at all)]
}
Does it run through: a) n times b) n+1 times c) n-1 times d) infinite times e) who the fuck wrote this shit. | | Thursday, June 30th, 2005 | | 5:35 pm |
Linker weirdness
OK, this is just plain weird. I'm not sure if stupid moron monkey boy is responsible for this directly but I feel compelled to blame him anyway. OK, I have two pairs of files, foo.[cpp|h] and bar.[cpp|h]. In foo.h we have:
class Line {
public:
Line::Line() { };
Line::~Line();
};
and in foo.cpp:
Line::~Line(){
free(thing);
}
OK, so far so good. Now, in bar.h we have:
struct Line {
Line::Line() { }
Line::~Line() { free(stuff) }
};
Now, in the project I'm working on, foo and bar are far enough away from each other that they don't interact at all and the person who wrote bar didn't even know that foo existed. The two different definitions of Line do completely different things, one's a line of text, the other is a line of data. Now, the weird thing is, that the destructor of the struct Line in bar.h never gets called. If you create a new Line from bar and then get rid of it, the destructor from foo gets called. Now foo expects there to be a thing, so when it points to this it inevitably gets something that's not a freeable pointer, and crashes. Now, I'm a little curious how this got past the compiler/linker. My hypothesis is that the object files for foo and bar both compiled fine, since foo and bar don't interact, but when the project got linked together, it became confused and made the destructor of bar point to foo instead. I dunno, this is my guess. Does anyone know what should happen in this situation? Is it valid code? Should the compiler give an error/warning? Should the linker give an error/warning? Should the whole thing just work the way it superficially looks like it should, without the bizarro cross linking? Either way, it wins my award for obscure bug of the afternoon. I would say obscure bug of the day, except I found something much stranger in a piece of hardware earlier :-/ Current Mood: curiousCurrent Music: Nothing - Rythmbox just died | | Tuesday, June 7th, 2005 | | 4:12 pm |
making the infinite finite
Today we see how to take an infinite loop and turn it into a finite one! observe:
while(1){
if(!foo) break;
do_stuff();
}
It's such a clever trick it almost brings a tear to my eye. Current Mood: tearfulCurrent Music: Guns 'n Roses - Locomotive | | Monday, June 6th, 2005 | | 3:40 pm |
and it continues
To follow up from the last post, we see the same thing achieved but in a slightly different manner.
if(foo){
goto LABEL;
}else if(bar){
LABEL:
do_stuff()
}
The ability to emulate logical or in so many different ways shows what a high standard of intellect was responsible for developing this software. I hope one day I can reach these levels. Current Mood: flabbergastedCurrent Music: AC/DC - High Voltage | | 3:26 pm |
More goto goodness
Carrying on from previous entries on using goto to emulate other control statements, we will today see how to avoid those pesky "logical or" statements (watch out, if you don't #define or || they can be even harder to use). So, without further ado I give you:
for(stuff){
if(foo){
LABEL:
do_things();
continue;
}
if(bar){
goto LABEL;
}
}
See how the goto allows the code to jump back up just in case there's another situation where you need to do_things(). This will save you lots of headaches later when you need to try to work out what your code was doing. Stay tuned for more fun and games. Current Mood: bemusedCurrent Music: Dire Staits - Heave Fuel | | 2:45 pm |
teh funny
This is without a doubt the funniest thing I've seen on the internet in ages. Note: Should you get multiple copies of this e-newsletter, please forward one to a friend, colleague, or family member.
Source Current Mood: amusedCurrent Music: The Ataris - Eight of Nine | | Thursday, May 26th, 2005 | | 10:27 pm |
Stupid monkey man
I've just spent the past 3 days refactoring a bunch of code and I have once again been amazed by the ineptitude, incompetence and the unprofessionalism of the person who originally wrote the code. The code started off as a single C++ file of approx 4200 lines. This included any number of classes and functions which were dedicated to visualising data. At a rough guess I would say that 75% of the code had been clagged (presumably at some point part of it was the original code but who could say). The amount of claggage was painfully obvious as well. It wasn't a couple of blocks of code here and there, it's entire classes. Once the code had been copied and slightly modified to do something slightly different it would stay that way until a bug was found. When a bug was found it'd get fixed in one place but not in the other. I spent hours and hours trying to consolidate this mess. For every block of code which was obviously clagged, I'd have to look at the minor differences in each case, work out which ones were bug fixes and which ones were genuine places where he wanted it to do something different. In almost all cases it was the former, proving how bad an idea it is to clag code. Anywho, this monstrosity has now been moved out into it's own directory, split into 6 or 7 files of reasonable size, had its class structure reworked and is almost beginning to resemble a workable piece of software. I still need to go through and document the entire thing (did I mention there were approximately fuck all comments in this 4200 lines (save for a few which had been clagged around, which made it easier to find duplicate code)). I don't understand how someone could have created this mess and not realised something was wrong. At times in the past, when the creator was still working with us, I'd pull out a single class into a separate file, just to put it somewhere sane, and a week later he'd have actually put it back into the big file claiming "it's easier to find stuff when it's all in one place". And it's not just the overall structure of the code that's bad, it goes right down to the smallest detail with the wrongness. Again I found myself putting else statements in to replace the gotos which had been used. If ever there was a case for minimum acceptable standards of products in code then this one file would be it. Current Mood: irritatedCurrent Music: None because my laptop's fucked | | Friday, May 13th, 2005 | | 1:51 pm |
yay goto
Today's example of substituting goto for other control statements shows how to simulate an else block. The basic structure is as follows:
if(foo){
[do stuff]
goto LABEL;
}
[do other stuff]
LABEL:
Note how easily the ever confusing else block is avoided, saving a whole bunch of typing getting everything indented one block across. This technique should, however be used sparingly. It's most effective if you place LABEL a couple of pages down in the code. This way you're getting the most savings in time and effort. Current Mood: annoyedCurrent Music: Foo Fighters - My Poor Brain | | Monday, April 25th, 2005 | | 1:30 pm |
Long time, no post
So, it's been a while since I've had anything to rant about on here so I thought I'd better put something in to fill up space. To paraphrase Axl Rose, this is normally the part where I talk about what's pissing me off, , but nothing's pissing me off right now.
At work I've been spending most of my time doing monkey work, which is horribly boring, but generally doesn't give me reason to get pissed off at things, since all the monkey work involves doing stuff with code I've written, which sucks much less hard than all the other code.
In other news, I've postponed my thesis, since I wasn't actually doing any work on it and wasn't finding it especially interesting. I'm going to pick up a new topic next year, something to do with brainwaves, havn't decided exactly what yet, but I'd like to try to fill in some of the gaping holes in the methodologies used for all the signal processing stuff we do. It seems to me that the entire field with one big open problem just waiting to be solved.
All the papers I've read so far seem to have nice ideas, but they're all tightly tailored to a specific subject set and don't generalise well. I'd like to find a way to generalise things so we can get good results across a huge range of paradigms and subject groups. Dunno how well it'll work but I guess we'll find out in a years time or so.
Current Mood: optimistic Current Music: Foo Fighters - February Stars | | Friday, April 1st, 2005 | | 2:44 pm |
Mmm... standards
Standards are really useful. They prevent people from reinventing wheels, they let people communicate between different, independent systems, and in general, if used properly, can save a shitload of work. So when someone goes out of their way to not use a standard because they "don't like it" it makes life difficult for everyone. This, as you may have guessed, is the situation I have to deal with at work. The subtle beauty of the situation is that the non-standard file format which was "designed" by this guy in such a way that it closely mimics the standard, but has just enough differences that tools which work on the standard don't work on his files. This means in turn that all the tools we use on these files have to be hand written. The thing that really shits me is that the standard file format is actually flexible enough that the guy could have stuck with the standard and avoided the parts of it which he didn't like. There was no need for a new file format, he could've just used a particular subset of the standard and things would be fine. It's shit like this that makes me wonder how this guy has survived in the industry for so long. Blerg, stupid fucker, glad he's not here any more and I can slowly go about unfucking all his shit. Current Mood: bitchyCurrent Music: Midnight Oil - Quinella Holiday |
[ << Previous 20 ]
|