- 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
Excellent stuff! If you can't put some humor in coding then where can you?
Admin
Hey, at least the kid had the excuse of being a student. Some of us have to deal with this crap in the real world with alleged 'professionals'.
That said, I do love the name, and if "-18 for sucking at life" is true, extra points for hilarity. :-)
Admin
Ugh. You know, if either of you had been that kid, you would have escilated that, and the prof, or some other higher-up, would have been forced to do something, and the kid would likely have been given a higher grade which they did not deserve.
<ul>
<li>-4 for poor name.</li>
<li>-4 for unneccessary cast</li>
<li>-6 for dereferencing a freed pointer</li>
<li>-6 for not having an exit condition</li>
</ul>
Same grade, but penilizing people for "sucking at life" is simply not a valid thing to do.
Admin
And what about penalizing him for dereferencing a void pointer? I think the "significant names for variables and functions" is a bit subjective but compiler and error warning are worse than a funny name.
Admin
Note: It is perfectly legal to call free() with a null-pointer. It simply does nothing.
Now our score improved to -19.
But you should never use a pointer after freeing it. Back at -20.
;-)
Admin
> Same grade, but penilizing people for "sucking at life" is simply not a valid thing to do.
Although I agree with the wording, I would have cut the poor name and unnecessary cast demerits in half, and then added "-4 for turning in obviously broken code that you haven't tested, wasting my time."
(Sometimes, btw, a cast that may be unneccessary is in fact there sometimes to explicitly force a certain type promotion, or make an implicit promotion explicit. This is especially true when working with third-party libraries; if you find yourself doing this with your own code, overload your function for the original type if it is suitably meaningful.)
Admin
Mr. Mastros, my impression is that the student so penile to begin with that no TA could've made him any more so.
l33t h4x0r d00d: The problem is that he'll end up dereferencing NULL when he recurses -- or at least he will be if he set tail->next to NULL when he built the list. Anybody here trust him to have gotten that right? Yeah, me neither... In that case, at the end of the list he'll follow a gibberish pointer to Podunk and end up with an access violation. Unless he accidentally used calloc() instead of malloc().
I did once work with somebody who thought that the C++ delete operator set the pointer to NULL. So he'd always say
if ( p ) delete p;
...and then do it again for the same p later on. He ultimately decided that operator delete "wasn't working right"; it was "just corrupting the object instead of deleting it".
Admin
Any pointer turns into void *. That's why the cast is wrong -- it's unnecessary, and it stops the compiler error if you accidentally pass the wrong type of variable (due to a typo, say).
Admin
> ... you would have escilated that...
> <li>-4 for unneccessary cast</li>
> ... but penilizing people for "sucking at life" is simply not a valid thing to do.
-3 for misspelling "escalated", "unnecessary", and "penalizing"
-3 for poor grammar
No penalty for sucking at life
Admin
I do not know why some people are surprised at stupid names? When it comes down to code that will be looked at only once and is not a "critical" piece of code for my classes, I have some stuff like this:
program SomeStupidTestThatWasDecidedToBeWrittenOneDayBeforeHolidays;
begin
writeln('You are a stupid user! And because I am the most intelligent piece of code, I can predict that you want to exit out this programme right now... press any key to exit.');
readkey;
writeln('Fooled yea! The stupid piece of code will be executed momentarily...');
delay(10000);
{... actual code ...}
end.
Jeez! This is what I do for fun just BECAUSE I have to code in Pascal for school.
Admin
Ha hah ahaha
Obviously none of you guys went to CMU.
At CMU it is perfectly valid to tell someone they suck at life. Although it should be a given, since you are an undergrad at CMU.
Admin
The problem is not checking for NULL before freeing the pointer, the problem is not checking for NULL as an exit condition. Even dereferencing NULL is a secondary problem. Since this code is dereferencing the pointer only after it is freed anyway, the value it held is ultimately irrelevant at that point.
Admin
When I was in college we had a Scheme professor (he also taught a C++ class the following semester) who could barely speak English and was a mediocre teacher in general. One of my friends took to turning in all his assignments with every variable, function, etc. named "thingy" or a variation on the word or a profanity.
Got at least a B in both classes, probably a B+ or A (been a few years).
Admin
Heh. You said "penilizing"
Admin
i was that kid, well not in the example, but in my class. i was docked 15% in a programming exam, of which i got 85% BTW, for not having a button other then the standard windows one, for killing the program. there was a menu, there was the windows one, the program did everything it was ment to do on the spec, but the ba****d docked me 15% for not having a button. still pi**ed of to this day because of it. still got an A but thats not the point.
Admin
We actually had someone at Uni submit his haskell code with functions along the lines of "HaskellIsCrap", "B*****dHaskell" and so forth.
He even got reasonable marks, considering that half the functions didn't work that is.
But then even I managed to get some RIP acronyms into my Prolog.
Admin
> QUOTE:
> Note: It is perfectly legal to call free() with a null-pointer. It simply does nothing.
As stated above - he should have checked it and exited, and also - lucky you that you only code on PC-platform :) I code on embedded (mostly m68k) systems, and calling "free(0);" on some platforms is a quick (and dirty?) trick for an instant reboot... I know - not really standard C, but good practice to avoid such things from happening imho, and if you know this, this can be real handy, the resetting of a system is most of the time some obscure system call. free(0) is a LOT easier :D
Disclaimer: the free(0) trick is only used in debug versions of these platforms supporting this "feature" to indicate something really really bad went wrong :)
Also another remark, this implementation is pritty stack-intensive (at least if working with a stack-oriented platform/compiler, but since most are...), even if the logic itself would be ok hence it's recursive behavior. I still wouldn't use it to free a linked list of 10.000 items :) Offcourse some compilers optimize this into a loop, but I don't like that that much :)
Admin
On some UNIX systems they used to set the word at zero to zero so indirecting through an extra null pointer was mostly safe. For all I know some platforms (SCO, maybe) still do this. On those platforms he'll get a segfault or bus error when he blows the stack instead of when he follows the null pointer to madness or blows out on a protection fault.
He's also depending on malloc allowing one use-after-free. With a debugging malloc or a secure free he'd hit a wild pointer or a null poiinter right off no matter what the list is.
Admin
Just for the record;
free( head ); // does NOT make head==NULL
and so
FreeThisSchnizzle( head->next );
will NOT dereference a NULL ptr, it will pass
the value at offset of member next after the pointer head, which still retains it's previous pointer value.
What actually happens is implementation dependant, behaviour will range from "works as expected" to a segfault / bus error ...
Admin
> free( head ); // does NOT make head==NULL
No, but recursing through a linked list with the end node marked by having a null next pointer does (eventually, after you call FreeThisSchnizzle() on that null next pointer).
>What actually happens is implementation dependant,
No, it is undefined. Were it implementation dependant then any given implementation would have to document its behaviour (which may be completely up to the implementation, or one of a few possible options).
As both derefencing a null pointer and dereferencing a pointer to an object that has been freed are undefined a compiler can do whatever it wants, and this can change between releases of the compiler without any warning. It can also change depending on debug options (and they often do, as debuggers will try to catch just the two errors above, assuming the compiler didn't already catch the fact that the function never returns).
Relying on implementation dependant behaviour is generally a Bad Thing but ocassionally necesary (in particular in very low-level code). Relying on undefined behaviour is just wrong. As a coder (rather than a compiler developer) it's best to read "undefined" in the standard as "Breaks. Horribly."
>behaviour will range from "works as expected" to
It is recursion without a condition that will stop the condition.
It might just be (not sure) theoretically possible for a compliant compiler to:
1. Not break at the use of a feed pointer.
2. Not break at the dereferencing of a null pointer.
3. Optimise the tail-recursion into an iteration, so there is no stack overflow[].
4. Realise that the iteration is no longer doing anything after it has reached the null pointer and optimise it away, to a more efficient behaviour that is the same "as if" it hadn't optimised; i.e. putting the thread to sleep (but not killing it, unless there was no references to the thread's handle stored)
5. Making the thread permanently sleep isn't a disaster for the rest of the program.
The success of this would be just slightly less dependent on luck than if you gave the same assignment to a blind monkey with carpal tunnel syndrome.
[] The only thing that indicates any method in the madness in FreeThisSchnizzle is that while the recursive call clearly should be before the call to free it may have been put at the end in the hope of making the recursion tail recursion and hence allowing the compiler to quite easily make it an iteration.
Admin
Jon Hanna : "As both derefencing a null pointer and dereferencing a pointer to an object that has been freed are undefined"
dereferencing NULL is perfectly valid and defined ansi-c !
( avoiding if(x) free (x) constructs, simply results in a NOP)
Admin
meant freeing
SRY
Admin
>> free( head ); // does NOT make head==NULL
>No, but recursing through a linked list with the end node marked by having a null next pointer does (eventually, after you call FreeThisSchnizzle() on that null next pointer).
Point is that it won't (legally) recurse -- the damage (de-referencing an already freed pointer) is done on the first iteration so the NULL at the end is technically irrelevant
Admin
I'm surprised no one pointed out that the recursion doesn't terminate (until you run out of stack space, that is).
Admin
Haha... that was me.
The TA, not the student. :P
Admin
And looking back... Levi sent in the wrong code there. The exact code from my records was such:
void freeThisShnizzle(Word *node)
{
if (node!=NULL)
freeThisShnizzle( node );
free(node);
}
Note that our recursive call is before our call to free... additionally nothing is ever set to null. I rapidly ran out of stack space when running this student's code, and then when I saw why...well... I thought he deserved a more specific penalty than a flat -20.
Admin
Somebody, just sent me this link. I am the person who wrote this code. Apparantly people still talk about this. Some guy came up to me in graphics last semester talking about it, and nearly wanted my autograph when I told him. I've still got a video of the class in which everyone laughed at me if anyone wants it [:D]. The code listed a few posts up is what I turned in, not the one in the first post, and the first -1 was for turning in an infinitely recursive function.
In my defense, this class isn't very serious, as its just a half semester intro to c, and for christ's sake, the labs were due on friday night!
Admin
Actually, I made a mistake. The -18 was for the infinite recursion, and the -1 was for sucking at life.
Admin
Sorry for the spam, but here's the video http://www.andrew.cmu.edu/user/rmoulton/FreeThisShnizzle.wmv
Admin
What about "using recursion when iteration will do the job"?
Admin
Ok, let's reflect on this a moment. A person, in attempting to offer some code to TheDailyWTF,
(a) inadvertantly fixes the one error in the code, but
(b) injects three NEW errors into it!
Now, that's a WTF!
Admin
The original code would have caused this statistic in one of our programming classes:
Admin
Can I tell you all a joke I read on the internet?
Okay...here goes.
Why was Snoop Doggy Dogg carrying an umbrella?
Fo' Drizzle.
Admin
Admin
Admin
Didn't anyone find the Snoop Dogg joke funny? I did.
That sort of "speak" makes me laugh.
Everytime I hear someone say something like "Fo' heezy" or "That's the sheezy." I have to say "Bless you." because it sounds like they sneezed.
Admin
I don't think that joke is funny because I don't speak that language. I never heard those expressions before.
Please translate them into English.
Admin
Y'know, I would love to translate them for you, however I myself don't know what they mean.
I just think they sound funny.
Admin
A-skizzle! A-skizzle!
Excuse me...
I had to sneeze. [:^)]
Admin
You're excuzzed.
Admin
So I was actually in this class, and the best part was when the TA put the code up on the monitor:
"Ok everyone, what's the problem with this code?"
"uhh . . it's an infinite loop that will overflow the stack space?"
"No! The problem is that it's named FreeThisSchnizzle!"
Admin
And possibly not even then, if (for example) it were compiled with gcc 3.* using the -foptimize-sibling-calls switch (or -O2, which includes that one). That makes it one of the few valid arguments against TCO I've seen.
Admin
You're confusing "implementation dependant" with "implementation-defined", which is standardese for what you describe. Argument from authority: I know what I'm talking about, because I had to read the C99 standard for money. ;-p
Admin
You meant freeing
NULL
is valid ANSI-C, but actually, dereferencingNULL
is also valid ANSI-C. Only if you do anything useful with the dereferenced pointer is the behavior undefined.For example, C99 explicitely states that
&*p
for a pointerp
is equivalent top
, even ifp == NULL
.Admin
This is the only valid WTF justification I have seen on these boards so far!
Admin
(OK, it's actually in the C++98 standard)
Admin
I once worked on a project that had so much code like this, they simply changed the "free" function so that it free's whatever you passed it on the previous call to "free" and saves this pointer to free NEXT time.
I couldn't understand how they could ever get to this point. All the ways I could imagine this happening had "checking and egg" issues. Why write the "delayed free" if you didn't have code like this? And why write code like this if you had a "delayed" free?
I finally tracked down the history. They once had a bug just like this, and as a quick workaround (it wasn't as trivial a fix as this example) they wrote the "delayed free" function. The problem was solved, so why mess with it? Over time, more bugs crept in that weren't detected because "delayed free" hid them, so over time, they just started writing to the "delayed free" model.
YUCK.
Admin
Can't we keep this kind of stuff in-house?
Admin
Great Post!
This kid sounds like such a douche! He tried to implement HUMOR into an entry level computer programming class?
We all know programmers (as a group) tend to be taken very seriously, so this type of behavior only makes us look uncool.
.......
.....
...
Admin
Yeah but you supposedly want to stop the recursion eventually.