Re: Debugging retainCount
Re: Debugging retainCount
- Subject: Re: Debugging retainCount
- From: publiclook <email@hidden>
- Date: Tue, 15 Jul 2003 09:02:57 -0400
On Monday, July 14, 2003, at 10:56 PM, The Amazing Llama wrote:
I had a memory leak in my program where I was autoreleasing too often
(which is the memory leak I always seem to have), and I think I've
figured out a simple way to track these things down.
This is not a leak. It is a crasher bug. Why aren't you following the
simple rules ?
Why couldn't NSObject be enhanced so that every time it gets an
-autorelease message, it increments a counter. It then checks this
counter against it's retainCount and debugger-breaks if the pending
autoreleases are greater than the retains.
One reason you might not want this is because some people could
legitimately write code like the following:
[someObject autorelease]; // default behavior is to get rid of
instance
if([someObject hasSpecialProperty])
{
// We want to keep this one after all
[someObject retain];
}
Simply comparing to the retain count may not be not good in this case.
I do agree that the number of autoreleases should not exceed the total
number of retains plus one. You would also need to check if there are
too many autoreleases (pending releases) each time an object is
released as well because that changes the retain count.
I could do this myself with a poseAs: but I don't know how to
decrement the counter on getting a release from the autorelease pool.
I suppose you could check the stack, but that seems a little hackish.
You can implement your own version of NSAutoreleasePool. Doing so
might be educational anyway. There is no magic involved.
However, this would make a very nice, very simple addition to the
frameworks, but making the NSAutoreleasePool decrement the counter
before calling -release.
How about NSZombieEnabled ? How about using -release instead of
-autorelease whenever possible ? Then you crasher bug will crash
immediately when you send the bogus message. Seriously, This is not
rocket science.
Unless (as I probably am) I am overlooking something simple that makes
all this impossible. Would this work?
It is not impossible at all. I suggest writing your own implementation
of NSAutoreleasePool and then use categories or poseAs to replace
NSObject's -autorelease message with on that uses your pool instead.
When your pool gets around to releasing its contents, it can perform
extra checks. When objecst are added to your autorelease pool, you can
do any diagnostics you want.
Before you get too carried away, look at NSDebug.h
NAME OF ENV. VARIABLE DEFAULT SET TO...
NSDebugEnabled NO "YES"
NSZombieEnabled NO "YES"
NSDeallocateZombies NO "YES"
NSHangOnUncaughtException NO "YES"
NSEnableAutoreleasePool YES "NO"
NSAutoreleaseFreedObjectCheckEnabled NO "YES"
NSAutoreleaseHighWaterMark 0 non-negative integer
NSAutoreleaseHighWaterResolution 0 non-negative integer
+ (void)enableRelease:(BOOL)enable;
// Enables or disables autorelease pools; that is, whether or
// not the autorelease pools send the -release message to their
// objects when each pool is released. This message affects only
// the pools of the autorelease pool stack of the current thread
// (and any future pools in that thread). The "default default"
// value can be set in the initial environment when a program
// is launched with the NSEnableAutoreleasePool environment
// variable (see notes at the top of this file) -- as thread
// pool-stacks are created, they take their initial enabled
// state from that environment variable.
+ (void)showPools;
// Displays to stderr the state of the current thread's
// autorelease pool stack.
+ (void)resetTotalAutoreleasedObjects;
+ (unsigned)totalAutoreleasedObjects;
// Returns the number of objects autoreleased (in ALL threads,
// currently) since the counter was last reset to zero with
// +resetTotalAutoreleasedObjects.
+ (void)enableFreedObjectCheck:(BOOL)enable;
// Enables or disables freed-object checking for the pool stack
// of the current thread (and any future pools in that thread).
// When enabled, an autorelease pool will call the function
// _NSAutoreleaseFreedObject() when it is about to attempt to
// release an object that the runtime has marked as freed (and
// then it doesn't attempt to send -release to the freed storage).
// The pointer to the freed storage is passed to that function.
// The "default default" value can be set in the initial
// environment when a program is launched with the
// NSAutoreleaseFreedObjectCheckEnabled environment variable
// (see notes at the top of this file) -- as thread pool-stacks
// are created, they take their initial freed-object-check state
// from that environment variable.
Seth A. Roby The Amazing Llama < mail or AIM me at tallama at mac
dot com>
"Life is like an exploded clown. It's really funny until you figure
out what just happened."
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.