I'd like to use gdb or Xcode's debugger to watch every message sent to an object in an Objective-C 2.0 program. I don't care about arguments and such, as I just need to see every message it receives (retain, release, autorelease, etc). I also don't want to profile my entire program.
Is there a means, in Xcode, to select an instance (possibly by address) and say "show me every message sent to this object"? Since the plumbing is fairly standard, I imagine there would have to be a probe hook or something. Anyone ever done this?
(Aside from subclassing the object in question, of course; looking for a more general solution.)
This is for iPhone development with Xcode 3.2 on Snow Leopard.
You can set the NSObjCMessageLoggingEnabled environment variable to YES and then grep/filter through the resulting log for the object you're interested in.
Here's a relevant blog post as well, though I'm not sure how much of the information there is still true in the runtime today. (It might all be. I really don't know.)
Related
My crash reporting service is showing a large number of mystery crashes for an iOS app. For a few reasons I suspect the code is trying to perform a selector on an object that doesn't have the particular selector.
How can I statically analyze the code to find the erronous selector?
I'm writing Objective-C code using Xcode 4.6 on OS X 10.8. I'm ok with a tool that doesn't pick up things like calling performSelector where the selector is built from a string etc. I think a basic tool will work.
Select "Analyze" from the "Product" menu in Xcode. Or press shift+command+B.
It's invaluable for identifying routine memory management stuff in MRC. But it's still useful for ARC programs.
You might also want to try setting an exception breakpoint for all exceptions.
I'd also refer you to the Debug and Tune Your App section of the Xcode User Guide. Or Ray Wenderlich's My App Crashed, Now What? series.
By the way, while the analyzer helps, I don't think it will find incorrect selectors. You might want to share how you're using selectors, because it you're using performSelector, there are often better patterns. Sometimes you have to use it, but frequently there are other patterns that are more robust. Or if you absolutely need to use selectors, add runtime respondsToSelector checks. For example:
NSAssert([object respondsToSelector:#selector(someMethod:)], #"%# does not respond to selector someMethod:", object);
Or, conditionally perform the selector if it responds to it (this is how you perform a method that might be conditional on a particular iOS version):
if ([object respondsToSelector:#selector(someMethod:)])
[object performSelector:#selector(someMethod:)];
Is there a way to find a Zombie at runtime in objective-c?
I'm looking for a way to prevent an object to call a method on a zombie, is there any way to detect one without making the app crash?
I do know about weak reference under ARC iOS5 and common sense programming practice.
I was thinking that a way could be asking the object size (I know that maybe "inside" there are just reference) but if the object still exist it should give a value, if it doesn't probably just the single pointer size.
Using malloc_size(pointerToObject)
Could it work?
UPDATE:
I do know how to run Instruments for Zombies detection
I don't think Andrea is asking how to run instruments to detect zombies, I think she wants to guard against calling a dealloced instance at runtime. I'm not sure what malloc size will return in this case. I think anything you come up with short of what they've done with NSZombies (which is to never truly free instances) will be gimicky and only work part of the time. I think your best best is the boring old diligent programming and profiling with instruments to guard against making these calls rather than trying to catch the error at runtime.
Try running the application with Instruments, and select the "Zombies" template.
On the scheme menu (upper left, next to run/stop). Select "Edit Scheme...". A sheet will appear. Select the Run/Debug scheme there. Select the "Diagnostics" tab on the center pane. Check Zombies.
I am new to mac os X development ,I downloaded an open source mac application ,but i couldn't able to understand the flow of execution of cocoa program.so any one can explain the program flow of a general cocoa program briefly.
Thanks in advance
Start in main. It's not likely to contain anything interesting, but worth checking just in case. Most probably, it will contain only a call to NSApplicationMain, which will create the NSApplication object and send it a run message. That's what gets the application running, and this method will run for the rest of the rest of the process.
Then look in the MainMenu nib. Loading this is one of the first things the application will do. Any windows here that are set as “Visible on Launch” will come up immediately; more importantly, the application delegate will probably be here. Check the application's or File's Owner's (the application is both of them in this nib, so you need to check both) delegate outlet, and if one of them is connected, follow the connection. See what class that object is an instance of.
Once you've found the application delegate class, open it up in Xcode. Look through the list of application delegate methods and find which ones are implemented, and read the ones that are. The application:…FinishLaunching: twins will be particularly important at the start of the process.
From there, it's all just reading code, seeing what it does, and going where it takes you.
Peter's answers are good - I'd also say to check for implementations of 'awakeFromNib', especially for object loaded from MainMenu.nib. You often find interesting things stashed away in that method, rightly or wrongly.
I'm having a bug in my Objective C program which causes the machine to crash hip deep in some library methods, and it's all library methods down the stack to main (Which I haven't touched from the one XCode gave me). So, I have a bit of a mystery.
The error I'm getting is:
Program received signal: “EXC_BAD_ACCESS”.
Now, I'm sure that this means that somewhere I'm releasing something too many times, or something like that. This is the objective C version of a seg-fault, right?
My question is: Since it's not happening in my own code, is there some clever way of tracking down what I'm double releasing? or is code inspection the best bet?
thanks.
EXC_BAD_ACCESS essentially means that you're trying to access or use a specific chunk of memory in an unexpected way. For example, if you try to send a message to a memory reference that no longer represents a valid object. It's different from a segmentation fault, but related.
See this related SO question for suggestions on debugging over-released objects. NSZombie will work wonders for you. Once you get your hands on Snow Leopard (you're getting it this Friday, right?) use the Zombies instrument to simplify the process, and use the Xcode static analyzer to help you find such errors at compile time.
Also visit: http://www.cocoadev.com/index.pl?DebuggingTechniques and this Apple Tech Note.
Memory (and resource) leaks happen. How do you make sure they don't?
What tips & techniques would you suggest to help avoid creating memory leaks in first place?
Once you have an application that is leaking how do you track down the source of leaks?
(Oh and please avoid the "just use GC" answer. Until the iPhone supports GC this isn't a valid answer, and even then - it is possible to leak resources and memory on GC)
In XCode 4.5, use the built in Static Analyzer.
In versions of XCode prior to 3.3, you might have to download the static analyzer. These links show you how:
Use the LLVM/Clang Static Analyzer
To avoid creating memory leaks in the first place, use the Clang Static Analyzer to -- unsurprisingly -- analyse your C and Objective-C code (no C++ yet) on Mac OS X 10.5. It's trivial to install and use:
Download the latest version from this page.
From the command-line, cd to your project directory.
Execute scan-build -k -V xcodebuild.
(There are some additional constraints etc., in particular you should analyze a project in its "Debug" configuration -- see http://clang.llvm.org/StaticAnalysisUsage.html for details -- the but that's more-or-less what it boils down to.)
The analyser then produces a set of web pages for you that shows likely memory management and other basic problems that the compiler is unable to detect.
If your project does not target Mac OS X desktop, there are a couple of other details:
Set the Base SDK for All Configurations to an SDK that uses the Mac OS X desktop frameworks...
Set the Command Line Build to use the Debug configuration.
(This is largely the same answer as to this question.)
Don't overthink memory management
For some reason, many developers (especially early on) make memory management more difficult for themselves than it ever need be, frequently by overthinking the problem or imagining it to be more complicated than it is.
The fundamental rules are very simple. You should concentrate just on following those. Don't worry about what other objects might do, or what the retain count is of your object. Trust that everyone else is abiding by the same contract and it will all Just Work.
In particular, I'll reiterate the point about not worrying about the retain count of your objects. The retain count itself may be misleading for various reasons. If you find yourself logging the retain count of an object, you're almost certainly heading down the wrong path. Step back and ask yourself, are you following the fundamental rules?
Always use accessor methods; declare accessors using properties
You make life much simpler for yourself if you always use accessor methods to assign values to instance variables (except in init* and dealloc methods). Apart from ensuring that any side-effects (such as KVO change notifications) are properly triggered, it makes it much less likely that you'll suffer a copy-and-paste or some other logic error than if you sprinkle your code with retains and releases.
When declaring accessors, you should always use the Objective-C 2 properties feature. The property declarations make the memory management semantics of the accessors explicit. They also provide an easy way for you to cross-check with your dealloc method to make sure that you have released all the properties you declared as retain or copy.
The Instruments Leaks tool is pretty good at finding a certain class of memory leak. Just use "Start with Performance Tool" / "Leaks" menu item to automatically run your application through this tool. Works for Mac OS X and iPhone (simulator or device).
The Leaks tool helps you find sources of leaks, but doesn't help so much tracking down the where the leaked memory is being retained.
Follow the rules for retaining and releasing (or use Garbage Collection). They're summarized here.
Use Instruments to track down leaks. You can run an application under Instruments by using Build > Start With Performance Tool in Xcode.
I remember using a tool by Omni a while back when I was trying to track down some memory leaks that would show all retain/release/autorelease calls on an object. I think it showed stack traces for the allocation as well as all retains and releases on the object.
http://www.omnigroup.com/developer/omniobjectmeter/
First of all, it's vitally important that your use of [ ] and { } brackets and braces match the universal standard. OK, just kiddin'.
When looking at leaks, you can assume that the leak is due to a problem in your code but that's not 100% of the fault. In some cases, there may be something happening in Apple's (gasp!) code that is at fault. And it may be something that's hard to find, because it doesn't show up as cocoa objects being allocated. I've reported leak bugs to Apple in the past.
Leaks are sometimes hard to find because the clues you find (e.g. hundreds of strings leaked) may happen not because those objects directly responsible for the strings are leaking, but because something is leaking that object. Often you have to dig through the leaves and branches of a leaking 'tree' in order to find the 'root' of the problem.
Prevention: One of my main rules is to really, really, really avoid ever allocating an object without just autoreleasing it right there on the spot. Anywhere that you alloc/init an object and then release it later on down in the block of code is an opportunity for you to make a mistake. Either you forget to release it, or you throw an exception so that the release never gets called, or you put a 'return' statement for early exit somewhere in the method (something I try to avoid also).
You can build the beta port of Valgrind from here: http://www.sealiesoftware.com/valgrind/
It's far more useful than any static analysis, but doesn't have any special Cocoa support yet that I know of.
Obviously you need to understand the basic memory management concepts to begin with. But in terms of chasing down leaks, I highly recommend reading this tutorial on using the Leaks mode in Instruments.