Hard Light Productions Forums

Off-Topic Discussion => Programming => Topic started by: blackhole on May 15, 2009, 06:08:46 pm

Title: Defensive programming
Post by: blackhole on May 15, 2009, 06:08:46 pm
Quote from: Worse Than Failure
"Some programmers like to program defensively," wrote Sam, "and then there's some of my coworkers. This is found at the top of nearly every function of our C++ classes."

   if (!this) return false;
OW
Title: Re: Defensive programming
Post by: Flipside on May 15, 2009, 06:25:16 pm
I'm a contract man myself, if the wrong data is getting to your subroutines, then you should be taking things higher in the code, not bogging down your basic functions with checks, especially if it's a frequently called function, before you know it, you're performing checks that, on many occasions, shouldn't need to take place, every time the routine is called.
Title: Re: Defensive programming
Post by: portej05 on May 15, 2009, 07:14:10 pm
Personally, it depends if I'm writing library code or writing front-end code.
In the library, you do need to check and assert on NULLs (although, doing it in a class is probably REAL overkill), but in the front-end, you've got total control over stuff, so sometimes those checks aren't always necessary
Title: Re: Defensive programming
Post by: blackhole on May 15, 2009, 08:07:15 pm
They are checking to see if the THIS pointer is null. The freaking THIS POINTER! It the this pointer is null YOU COULDNT BE CALLING THE FUNCTION IN THE FREAKING FIRST PLACE.
Title: Re: Defensive programming
Post by: Flipside on May 15, 2009, 09:55:57 pm
Well, I'm not a C++ programmer, but yes, that looked somewhat ridiculous to me too, I think that's why I didn't bother commenting on it, because it's just too daft to make sense, it couldn't be null.

I must admit to never having been a large fan of the THIS function in the first place, I can understand its need to exist, but I've always felt it has the potential to be misunderstood and over-used, as that little bit of code exemplifies.
Title: Re: Defensive programming
Post by: Mongoose on May 15, 2009, 11:17:10 pm
It took me a Google search to even understand what was going on here, since "this" never came up in my few comp. sci. classes at school.  But yeah...ow.
Title: Re: Defensive programming
Post by: Bobboau on May 16, 2009, 12:48:36 am
it, could happen, I've seen it happen, but returning false is almost certainly the wrong thing to do here. throwing an error of some sort would probably be the better way to go.
Title: Re: Defensive programming
Post by: Uchuujinsan on May 16, 2009, 03:22:42 am
They are checking to see if the THIS pointer is null. The freaking THIS POINTER! It the this pointer is null YOU COULDNT BE CALLING THE FUNCTION IN THE FREAKING FIRST PLACE.
Wrong:
Code: [Select]
bool MyClass::ReturnTrue()
{
  return true;
}
MyClass* class = 0;
class->ReturnTrue(); //will return true
would return true without any problem
Code: [Select]
bool MyClass::ReturnTrue()
{
  return true;
}

//is converted by the compiler to:
bool MyClass::ReturnTrue(MyClass*)
{
  return true;
}

class-> ReturnTrue(); //is converted by the compiler to:
ReturnTrue(class);

//well, not exactly, but you get the idea
So, unless you do access member variables of the class, invoking a function on 0 is possible and valid.

Still, such checks are pointless in nearly all cases imho.
Title: Re: Defensive programming
Post by: blackhole on May 16, 2009, 03:25:39 am
That is true, but you should always always always check to ensure the pointer your using is not NULL before calling a function in a situation where it could be null, and if you ever DO call a function from a null pointer, you did something wrong. Therefore I should revise my statement to you SHOULDN'T be calling the function in the first place (I've had many bugs where the call stack would get corrupted because something returned an invalid pointer and I ended up calling a function on it).

But yes, the this pointer is really just another argument passed to the function in the EAX register, since computers aren't really object oriented. That doesn't make it any less stupid :p
Title: Re: Defensive programming
Post by: Uchuujinsan on May 16, 2009, 03:27:46 am
Therefore I should revise my statement to you SHOULDN'T be calling the function in the first place (I've had many bugs where the call stack would get corrupted because something returned an invalid pointer and I ended up calling a function on it).
I can only agree with you here :)
Title: Re: Defensive programming
Post by: blackhole on May 16, 2009, 03:29:34 am
Therefore I should revise my statement to you SHOULDN'T be calling the function in the first place (I've had many bugs where the call stack would get corrupted because something returned an invalid pointer and I ended up calling a function on it).
I can only agree with you here :)

SOMEONE AGREES WITH ME!

*Erik has a heart attack and dies*
Title: Re: Defensive programming
Post by: portej05 on May 16, 2009, 09:19:54 am
I do offer the following example from the ATL/MFC headers

Code: [Select]
_AFXWIN_INLINE CGdiObject::operator HGDIOBJ() const
{ return this == NULL ? NULL : m_hObject; }
(there are a bunch of other examples in there as well)

When I've figured out why it could be NULL, I'll stick it here\

EDIT: Here's a case you may not have considered (although, it is almost certainly a coding error):
Code: [Select]
MyAwesomeClass* pMAC = CreateNewAwesomeClass( );
pMSC->DoCoolFunction( );

If the function CreateNewAwesomeClass fails for some reason, and returns NULL, the call to DoCoolFunction will be done with the this pointer as NULL.
Another good reason why you should always check function return values.

EDIT2: Another bloody good reason to initialise your variables
Code: [Select]
MyAwesomeClass* pMAC;
pMAC->DoCoolFunction( );

The value of pMAC is NOT defined, and if the initialisation is skipped for any reason, a junk address will be referenced, and that is something that you cannot protect against.
Title: Re: Defensive programming
Post by: blackhole on May 16, 2009, 04:08:22 pm
That's exactly what I said :P
Title: Re: Defensive programming
Post by: Mika on June 17, 2009, 05:18:08 pm
I don't know about defensive programming, there seems to be some pretty good stuff on multiple sources why you should always check the stuff that's getting inside a function.

Ten Commandments of C
http://www.lysator.liu.se/c/ten-commandments.html

Commandment 3:
Quote
Thou shalt cast all function arguments to the expected type if they are not of that type already, even when thou art convinced that this is unnecessary, lest they take cruel vengeance upon thee when thou least expect it.

I'm considering breaking that one.