What I am looking for is a way to programmatically verify a target object has been deallocated. Currently I have an NSLog statement in the dealloc methods of the objects I wish to observe.
The unit testing framework is from the Google Toolbox for the mac, and it working nicely. I am just not certain how to frame this particular test.
Use _GTMDevLog :
See the Advanced Stuff | Unit Test Logging on this page.
More info on DevLogNAssert.
You could swizzle the dealloc method. See MethodSwizzling on CocoaDev; a modern approach using Leopard's new method_exchangeImplementations function is (currently) near the bottom of the page.
Your implementation will need to tell your test case object that it had been called. One way to do this would be a static variable in the file where both the test case class and replacement dealloc method are defined; your test method sets that variable to NO, then releases the object, then asserts that the variable's value is now true.
In the past I've created a variable that counts the number of objects of a given class that have been allocated by incrementing the value in the constructor and decrementing it in the destructor. The unit tests just check that the variable is zero at the end of the test.
I did something very similar to this in C#/.Net. I used a "WeakReference" to keep track of the item, and tested that it no longer existed (see link). Can you translate this approach to your environment?
Link
Could you record the dealloc in some kind of event monitor service, so that the test code can then query with that to see if the dealloc has occured. Obviously you will record it by name or id, as the object is being dealloc'd...
I may be naive, but wouldn't a unit test of a deallocation consist of
allocating an object,
deallocating it through your method to be tested,
trying to call something from the object, and then
catching the exception and see if its type is correct?
I’ve written a function that releases the object and returns YES if the object got deallocated:
BOOL getsDeallocatedByReleasing(id object);
There’s also an advanced interface where you can run arbitrary code in a block and you will get a bool indicating if an object of given class was deallocated:
BOOL classGetsDeallocated(Class c, void (^block)(void));
The code uses method swizzling, it’s pretty ugly and definitely not thread-safe, but it works. You can find it on GitHub, I’ll keep it updated if I find any bugs.
P.S. After writing all that code (d’oh!), wouldn’t it be possible to add a single retain at the start, do whatever you want, tear down the object graph you are inspecting and check the object’s retain count?
Related
So, at a breakpoint, I have a random object instance. I want to figure out which objects have a pointer to this object. Is there a way to see this in the debugger console? Maybe something that shows me all the objects that have a retain on the object?
Example: I have a NSViewController instance and I want to see all the other objects that hold a pointer this view controller instance. This would be helpful because it would allow me to see the view controller hierarchy that is encapsulating my instance.
Just a crazy thought I had that would really help at times.
In lldb, use command script import lldb.macosx.heap to install some memory-searching functions. The ptr_refs command should be able to do what you want; use ptr_refs --help to learn more.
Not an efficient solution, or applicable in all cases, but you could encapsulate the object you're looking for in an accessor method on one of your classes, and put a breakpoint inside. By stepping through the end of the accessor method, you can eventually see all the call points.
Alternatively, you can remove the definition of the variable, and the compiler will spit out a ton of errors, each will also be a call to this object.
I'd suggest using ARC if you're not already. Ideally your code wouldn't be messy enough that you wouldn't be able to identify references by reading through the code, ARC can help a little bit in that department
I would like to set a symbolic breakpoint on "objectAtIndex:" method of a specific property in a specific class.
See the following code :
#interface Foo
...
#property (strong,nonatomic) NSMutableArray *fooArray;
...
#end
I 've tried the following things:
-[[Foo fooArray] objectAtIndex:]
-[Foo::fooArray objectAtIndex:]
-[Foo::fooArray objectAtIndex]
Foo::fooArray::objectAtIndex:
Foo::fooArray::objectAtIndex
Foo::fooArray::objectAtIndex()
None of theses solutions work.
Any ideas to do the trick ?
Unfortunately, while this would be useful, it cannot work, for multiple reasons.
The first involves how methods are specified. A method signature for identifying a method in a breakpoint has three parts:
-¹[NSDictionary² objectForKey:³]
+¹[NSString² stringWithContentsOfURL:encoding:error:³]
Is this an instance method (-) or a class method (+)?
Which class's implementation of this method?
What's the selector of this method?
So your first problem is that what you have written for #2 is not a class.
What you do have is a class, followed in some fashion by a property name. This cannot work, because the debugger has no way to know whether that is a pure accessor—it cannot be sure that you, or whoever implemented that property, didn't write a custom accessor that does something else. This means that the debugger has no good, reliable way to obtain that value, or to know when that value changes, without potentially incurring side effects.
Moreover, the role of a class in a method signature is to identify which class provides the implementation you're setting a breakpoint on. That goes out the window as soon as you start trying to refer to a property that holds an object instead, because the debugger needs a class, and will have to get it from the object—and see the previous paragraph for some of the difficulties of knowing which object that is at all times.
(To be fair, it would indeed be possible for the debugger to watch the value of an instance variable—IIRC, both debuggers can already do this in a watchpoint, though reliability of watchpoints was flaky the last time I tried one. If the debugger could translate the property into its backing ivar, if it has one, and watch that, it would be a decent 90% solution for the majority of properties, which aren't backed by imaginative storage implementations and custom accessors. But the debuggers cannot do this today.)
The second reason is that NSArray is a class cluster.
You probably already know the first part of this (I suspect it's why you're trying to specify a single object by a property of another):
NSArray and NSMutableArray are both abstract classes, which in turn means that neither one implements the business of being an array; each one implements a bunch of convenience methods, while leaving a select set of core methods unimplemented, for subclasses to implement.
So, when you create an NSArray, you do not create an NSArray. The object you get back will be an instance of some private subclass of NSArray, with its own implementation of all of the details of how it manages an ordered list of objects.
So you could set a breakpoint on, say, -[NSArray objectAtIndex:], but it would never get hit, because nothing uses NSArray's implementation of objectAtIndex:—it would not make sense to use that implementation, because that implementation raises an exception (intended to catch subclasses that forget to implement it).
The part that breaks your question is:
While NSArray's implementations of various non-essential methods are defined ultimately in terms of the core methods, such as objectAtIndex:, that does not mean that subclasses are bound to use those implementations. A subclass could very well have its own implementations that don't use objectAtIndex:, if objectAtIndex: is not the most efficient way to do what they do (e.g., if the array is backed by a linked list rather than a C array).
So, to summarize this long answer:
It is not possible for the debugger to reliably watch the value of a property.
As such, it is not possible for the debugger to break when a method in the class of the object that is the value of that property is called, because the correct method to set the breakpoint on may change at any time, and the debugger cannot know when that happens.
Even if you could break on objectAtIndex: of some object identified by property, the array may validly never use objectAtIndex:, in which case your breakpoint would never get hit anyway.
You probably should ask another question about whatever you're trying to do by breaking on objectAtIndex:. I assume you're trying to investigate a bug in your app; that bug is probably another interesting question.
After some digging, I found a way to work this out. That's kinda ugly.
It involves creating a conditional breakpoint dynamically, in a command triggered by a first breakpoint.
First, break whenever your fooArray is ready. I settled on the fooArray accessor, but it could be done earlier :
breakpoint set --name "-[Foo fooArray]"
Then, what you want is break when objectAtIndex: is called on this specific array object. First let's put its pointer in a variable :
expr id $watch = self->_fooArray
and then create a new breakpoint, using this variable in the condition :
breakpoint set --name "-[__NSArrayI objectAtIndex:]" --condition "$rdi == $watch"
$rdi contains self, at least on x86_64. Use $r0 on ARM. (See Clark Cox's great post on the topic.)
-[NSArray objectAtIndex:] is never called. As Peter mentioned, NSArray is a class cluster, and your array is actually an __NSArrayI.
Or, in Xcode :
(Don't forget to check the "continue" box.)
It's not really beautiful, but it seems to work !
I am not at my Mac, so I cannot try this myself, but how about:
breakpoint set -n "-[[Foo fooArray] objectAtIndex:]"
I have read about how Objective-C runtime works, so please comment if I misunderstood something.
Let's say I have class called Person. That class may or not have method getSex.
Person *p = [[Person alloc]init];
Here the memory is allocated for Person instance (isa is created also which points to class Person), init is used to initialize Person ivar's
[p getSex];
Here objc_msgSend(Person,#selector(getSex) is called on Person class.
If Person class not have such method the runtime look for that method in Person root class and so on. When the method is found IMP is called which is a pointer to method block code. Then the method is executed.
Is that correct ?
Yes, everything is correct, except the behavior of init may or may not initialize all its member variables such that the accessors return valid results, although it is reasonable to guess that it initializes properties unless told otherwise.
There's one piece that's slightly off.
The call will actually be one of these three:
objc_msgSend(p, #selector(getSex))
objc_msgSend_fpret(p, #selector(getSex))
objc_msgSend_stret(p, #selector(getSex))
One difference here is that the first argument is to the object and not to the class.
Also, since you didn't share what the getSex method returns, it's not possible for us to know whether it will be one of the fpret/stret versions or not. If the method returns a double (on certain platforms), the fpret version will be used. If the method returns a structure value (on certain platforms), then the stret version will be used. All others will use the standard version. All of this is platform dependent in many different ways.
As the others said, allocation will create an object with all instance variables set to 0/NULL and a valid isa pointer as well. Initialization methods may or may not update the instance variables with something meaningful.
How would you write a unit test—using OCUnit, for instance—to ensure that objects are being released/retained properly in Cocoa/Objective-C?
A naïve way to do this would be to check the value of retainCount, but of course you should never use retainCount. Can you simply check whether an object's reference is assigned a value of nil to indicate that it has been released? Also, what guarantees do you have about the timing at which objects are actually deallocated?
I'm hoping for a concise solution of only a few lines of code, as I will probably use this extensively. There may actually be two answers: one that uses the autorelease pool, and another that does not.
To clarify, I'm not looking for a way to comprehensively test every object that I create. It's impossible to unit test any behavior comprehensively, let alone memory management. At the very least, though, it would be nice to check the behavior of released objects for regression testing (and ensure that the same memory-related bug doesn't happen twice).
About the Answers
I accepted BJ Homer's answer because I found it to be the easiest, most concise way of accomplishing what I had in mind, given the caveat that the weak pointers provided with Automatic Reference Counting aren't available in production versions of XCode (prior to 4.2?) as of July 23rd, 2011. I was also impressed to learn that
ARC can be enabled on a per-file basis; it does not require that your
entire project use it. You could compile your unit tests with ARC and
leave your main project on manual retain-release, and this test would
still work.
That being said, for a far more detailed exploration of the potential issues involved with unit testing memory management in Objective-C, I highly recommend Peter Hosey's in-depth response.
Can you simply check whether an object's reference is assigned a value of nil to indicate that it has been released?
No, because sending a release message to an object and assigning nil to a variable are two different and unrelated things.
The closest you can get is that assigning anything to a strong/retaining or copying property, which translates to an accessor message, causes the previous value of the property to be released (which is done by the setter). Even so, watching the value of the property—using KVO, say—does not mean you will know when the object is released; most especially, when the owning object is deallocated, you will not get a notification when it sends release directly to the owned object. You will also get a warning message in your console (because the owning object died while you were observing it), and you do not want noisy warning messages from a unit test. Plus, you would have to specifically observe every property of every object to pull this off—miss one, and you may be missing a bug.
A release message to an object has no effect on any variables that point to that object. Neither does deallocation.
This changes slightly under ARC: Weak-referencing variables will be automatically assigned nil when the referenced object goes away. That doesn't help you much, though, because strongly-referencing variables, by definition, will not: If there's a strong reference to the object, the object won't (well, shouldn't) go away, because the strong reference will (should) keep it alive. An object dying before it should is one of the problems you're looking for, not something you'll want to use as a tool.
You could theoretically create a weak reference to every object you create, but you would have to refer to every object specifically, creating a variable for it manually in your code. As you can imagine, a tremendous pain and certain to miss objects.
Also, what guarantees do you have about the timing at which objects are actually released?
An object is released by sending it a release message, so the object is released when it receives that message.
Perhaps you meant “deallocated”. Releasing merely brings it closer to that point; an object can be released many times and still have a long life ahead of it if each release merely balanced out a previous retain.
An object is deallocated when it is released for the last time. This happens immediately. The infamous retainCount doesn't even go down to 0, as many a clever person who tried to write while ([obj retainCount] > 0) [obj release]; has found out.
There may actually be two answers: one that uses the autorelease pool, and another that does not.
A solution that uses the autorelease pool only works for objects that are autoreleased; by definition, objects not autoreleased do not go into the pool. It is entirely valid, and occasionally desirable, to never autorelease certain objects (particularly those you create many thousands of). Moreover, you can't look into the pool to see what's in it and what's not, or attempt to poke each object to see if it's dead.
How would you write a unit test—using OCUnit, for instance—to ensure that objects are being released/retained properly in Cocoa/Objective-C?
The best you could do is to set NSZombieEnabled to YES in setUp and restore its previous value in tearDown. This will catch over-releases/under-retains, but not leaks of any kind.
Even if you could write a unit test that thoroughly tests memory management, it would still be imperfect because it can only test the testable code—model objects and maybe certain controllers. You could still have leaks and crashes in your application caused by view code, nib-borne references and certain options (“Release When Closed” comes to mind), and so on.
There's no out-of-application test you can write that will ensure that your application is memory-bug-free.
That said, a test like you're imagining, if it were self-contained and automatic, would be pretty cool, even if it couldn't test everything. So I hope that I'm wrong and there is a way.
If you can use the newly-introduced Automatic Reference Counting (not yet available in production versions of Xcode, but documented here), then you could use weak pointers to test whether anything was over-retained.
- (void)testMemory {
__weak id testingPointer = nil;
id someObject = // some object with a 'foo' property
#autoreleasepool {
// Point the weak pointer to the thing we expect to be dealloc'd
// when we're done.
id theFoo = [someObject theFoo];
testingPointer = theFoo;
[someObject setTheFoo:somethingElse];
// At this point, we still have a reference to 'theFoo',
// so 'testingPointer' is still valid. We need to nil it out.
STAssertNotNil(testingPointer, #"This will never happen, since we're still holding it.")
theFoo = nil;
}
// Now the last strong reference to 'theFoo' should be gone, so 'testingPointer' will revert to nil
STAssertNil(testingPointer, #"Something didn't release %# when it should have", testingPointer);
}
Note that this works under ARC because of this change to the language semantics:
A retainable object pointer is either a null pointer or a pointer to a valid object.
Thus, the act of setting a pointer to nil is guaranteed to release the object it points to, and there's no way (under ARC) to release an object without removing a pointer to it.
One thing to note is that ARC can be enabled on a per-file basis; it does not require that your entire project use it. You could compile your unit tests with ARC and leave your main project on manual retain-release, and this test would still work.
The above does not detect over-releasing, but that's fairly easy to catch with NSZombieEnabled anyway.
If ARC is simply not an option, you may be able to do something similar with Mike Ash's MAZeroingWeakRef. I haven't used it much, but it seems to provide similar functionality to __weak pointers in a backwards-compatible way.
this is possibly not what you're looking for, but as a thought experiment I wondered if this might do something close to what you want: what if you created a mechanism to track the retain/release behavior for particular objects you wanted to test. Work it something like this:
create an override of NSObject dealloc
create a CFMutableSetRef and set up a custom retain/release functions to do nothing
make a unit test routine like registerForRRTracking: (id) object
make a unit test routine like clearRRTrackingReportingLeaks: (BOOL) report that will report any object in the set at that point in time.
call [tracker clearRRTrackignReportingLeaks: NO]; at the start of your unit test
call the register method in your unit test for every object you want to track and it'll be removed automatically on dealloc.
At the end of your test call the [tracker clearRRTrackingReportingLeaks: YES]; and it'll list all the objects that were not disposed of properly.
you could override NSObject alloc as well and just track everything but I imagine your set would get overly large (!!!).
Even better would be to put the CFMutableSetRef in a separate process and thus not have it impact your program runtime memory footprint overly much. Adds the complexity and runtime hit of inter-process communication though. Could use a private heap ( or zone - do those still exist?) to isolate it to a lesser degree.
I'm looking for a way to make an NSInvocation invoke a specific IMP. By default, it invokes the "lowest" IMP it can find (ie, the most-recently-overridden version), but I'm looking for a way to make it invoke an IMP from higher up in the inheritance chain. The IMP I want to invoke is determined dynamically, or else I'd be able to use the super keyword or something like that.
My thought was to use the -forwardInvocation: mechanism to capture a message (easy and already working) and then alter the IMP so it goes to a method that is neither the super implementation nor the furthest descendent's implementation. (hard)
The only thing I've found that comes remotely close is AspectObjectiveC, but that requires libffi, which makes it non-iOS compatible. Ideally I'd like this to be cross platform.
Any ideas?
disclaimer: i'm just experimenting
Trying out #bbum's idea of a trampoline function
So I think I've got things mostly set up; I've got the following trampoline that gets correctly added via class_addMethod(), and it does get entered:
id dd_trampolineFunction(id self, SEL _cmd, ...) {
IMP imp = [self retrieveTheProperIMP];
self = [self retrieveTheProperSelfObject];
asm(
"jmp %0\n"
:
: "r" (imp)
);
return nil; //to shut up the compiler
}
I've verified that both the proper self and the proper IMP are the right things prior to the JMP, and the _cmd parameter is also coming in properly. (in other words, I correctly added this method).
However, something is going on. I sometimes find myself jumping to a method (usually not the right one) with a nil self and _cmd. Other times I'll just crash in the middle of nowhere with an EXC_BAD_ACCESS. Ideas? (it's been a long time since I've done anything in assembly...) I'm testing this on x86_64.
NSInvocation is just an object representation of a message send. As such, it can't invoke a specific IMP any more than a normal message send could. In order to have an invocation call a specific IMP, you'd either need to write a custom NSInvocation class that goes through the IMP-calling routine or you'd have to write a trampoline that implements the behavior and then create an invocation that represents a message to the trampoline (i.e. you basically wouldn't be using NSInvocation for much of anything).
Added long after the fact, for reference:
You can do it with private API. Put this category somewhere convenient:
#interface NSInvocation (naughty)
-(void)invokeUsingIMP:(IMP)imp;
#end
and voila, it does exactly what you'd expect. I dug up this gem from one of Mike Ash's old blog posts.
Private API tricks like this are great for research or in-house code. Just remember to excise it from your appstore-bound builds.
Given that you already have the IMP, you simply need a way to do a very raw forward of the method call to said IMP. And given that you are willing to use an NSInvocation like solution, then you could also build a similar proxy class.
If I were faced with this, I would create a simple proxying class that contained the IMP to be called and the target object (you'll need to set the self parameter). Then, I would write a trampoline function in assembly that takes the first argument, assumes it is an instance of the proxying class, grabs the self, stuffs it into the register holding argument 0, grabs the IMP and *JMPs to it as a tail call.
With trampoline in hand, you would then add that trampoline as an IMP for any selector on the proxying class that you want forwarded to a particular IMP....
To achieve any kind of generic mechanism like this, the key is to avoid anything having to do with rewriting the stack frame. Avoid the C ABI. Avoid moving arguments about.
An untested idea:
Could you use object_setClass() to force the selection of the IMP that you want? That is…
- (void)forwardInvocation:(NSInvocation *)invocation {
id target = [invocation target];
Class targetClass = classWithTheImpIWant();
Class originalClass = objc_setClass(target, targetClass);
[invocation invoke];
objc_setClass(target, originalClass);
}
I think your best choice is to use libffi. Have you seen the port to iOS at https://github.com/landonf/libffi-ios? I haven't tried the port, but i have successfully invoked IMP with arbitrary arguments on the Mac.
Have a look at JSCocoa https://github.com/parmanoir/jscocoa it includes code to help you prepare a ffi_cif structure from a Method and it also contains a version of libffi that should compile on iOS. (Haven't tested either)
You should probably have a look at how we swizzle the implementation of a certain method on an instance of an object in https://github.com/tuenti/TMInstanceMethodSwizzler
Basically, you swizzle the method for all object of a class so when its called it look up in a dictionary whats is the implementation which has to be called for the target object, falling back to the original implementation if not found.
You can also use the private invokeWithImp: method, but this is discouraged if you intent to submit the app to the store.
you could add the IMP to the class using class_addMethod under a new selector and invoke that selector.
the temporary method can't be removed though.