Checking for NULL (was "Re: Can't get setDelegate to work...")
Checking for NULL (was "Re: Can't get setDelegate to work...")
- Subject: Checking for NULL (was "Re: Can't get setDelegate to work...")
- From: "Mark D. Gerl" <email@hidden>
- Date: Wed, 4 Mar 2009 15:57:51 -0500
On Mar 4, 2009, at 12:11 AM, Michael Ash wrote:
On Tue, Mar 3, 2009 at 4:30 PM, Quincey Morris
<email@hidden> wrote:
On Mar 3, 2009, at 12:50, Nick Zitzmann wrote:
It doesn't seem to be documented, but I think it will return nil
only if
(1) there was not enough contiguous RAM in the program's VM space to
allocate the object, or (2) there was, but the user has run out of
disk
space for swap files. But if this happens, the program is pretty
much
screwed anyway, because it's going to crash.
Yes, I'm aware of the "is pretty much screwed" scenario, but I
think there
are in fact some recoverable scenarios. One involves a sequence of
very
large (valid) allocations gobbling up VM space so that it becomes
impossible
to create a humbler NS... object of some kind. If the application
doesn't
crash right away, returning nil (or NO) back through the sequence
could
release all the memory and allow the application to continue with
an error
message.
Another scenario is a memory-limited environment like the iPhone.
In either environment, once allocations start to fail for any reason,
you are doomed.
Recovery is possible, nay reasonable, if you control all of the code
in the process. But you don't, and you can bet that Cocoa is *not*
written with an eye toward gracefully recovering when malloc() begins
to return NULL.
You can try to recover from an allocation error, but what if the first
NULL allocation happens inside Cocoa code somewhere? If you're lucky
it'll end up trying to insert it into a collection or something
similar, trigger an assert, and throw an exception. If you're unlucky,
the NULL allocation will happen while trying to resize an
NSDictionary's hash table and you'll be set up for a crash.
Even if you could trap it and recover gracefully by dumping a large
allocation, multithreading means that you still have a window of
opportunity in between the failure and the allocation dumping where
other threads will see allocation failures too. And again, these can
happen deep in Cocoa code where you have no chance to survive.
Realistically, unless you're a pure libc program, the only way to deal
with out-of-memory situations is to detect it in advance and free up
memory *before* the allocations begin to fail, the way the iPhone
frameworks do it.
In an attempt to NOT derail my original topic, I've renamed this
thread (I hope)...
Perhaps it's because I come from the old school ways, I find it nearly
impossible for me to write code that doesn't check for NULL -
regardless of the API's documentation or intent. The one true thing
is that things can and do go wrong -- logically -- in computer
programs. So, I am just in the habit of always checking for NULL.
I'm just not yet that comfortable of stacking things up and doing the
Cocoa/Java way. I also wrap things up inside of try...catch blocks as
well, which will help protect in the case of legitimate memory
failure. Of course, in this case, if something as small as an NSMenu
fails due to memory issues, something's going to go terribly wrong.
However, loading a large image, maybe not - and (graceful) recovery is
much more possible.
Long ago in Classic MacOS programming days, we had some nice hooks
into memory heap allocation - and you could plug in a function that
would get called if a memory allocation failed, which would give you a
chance to deallocate cached data or to gracefully recover without user
data loss. I'm not as familiar with Cocoa (yet) as many on this list,
but I'd be surprised if the Obj-C/Cocoa system didn't have something
similar.
I also know that many mission-critical software development projects
employ their own memory management schemes - and don't rely on the
underlying Standard Lib stuff.
In any case, and perhaps based purely on habit, I find it difficult to
even write:
NSStatusItem statusItem = [[[NSStatusBar systemStatusBar]
statusItemWithLength:NSVariableStatusItemLength] retain];
...in favor of:
NSStatusBar *systemBar = [NSStatusBar systemStatusBar];
if (systemBar != NULL)
{
NSStatusItem statusItem =
[systemBar statusItemWithLength:
NSVariableStatusItemLength];
if (statusItem != NULL)
{
[statusItem retain];
...
}
}
There's something that's just "uncomfortable" about dereferencing
pointers without first checking for validity. Is it just me?
M
M
--
Mark D. Gerl, Multimedia Design Group, <mailto:email@hidden>
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden