I am having issues with something being released or not retained, and Xcode will not show me exactly where the error is at.
I am working collaboratively with an individual who has a horribly organized project, and I think Xcode is even freaking out, because [CALAyer release] is thrown, but no explanation of what or where.
For env variables, you can read NSDebug.h (use open -h NSDebug.h in the Terminal). Though NSZombieEnabled is the most useful one there. If you need to debug object lifetime issues, use Instruments with the Zombies instrument. You can then see all the retain/release/autorelease events that happened for any given object.
Related
I've been getting this random crash, in which I don't know how to reproduce again. It happens when I was browsing/using the apps for some time, switching views here and there and I got this:
First of all I don't know which UIImage is this crash referring to. I do have a crash report, but I don't know how to read it. I would like to reproduce the error, but I don't know how to.. it seems that it's quite random. Can someone help me out in debugging this?
Hard to say something for sure. This is my guess.
I see you are getting some data from an external source "convore.com". When you say you get the error randomly, I think it may be due to the data received from the convore.com api. Probably from time to time you are not getting the image, link, or graphics from the server and you don't create and image, and then you are trying to retain it, causing the error.
Without being able to reproduce the failure, it will be very hard.
If you cannot reproduce it, I would suggest building your project by using the Xcode option "Build and Analyze". Indeed, since this is seemingly a problem with retain/release, "Build and Analyze" could give you some hint at where things go bad. By the way, if you are not doing it, it is highly suggested, almost mandatory check.
You could try and post the crash report, but I doubt it will be useful. The point is finding out where the UIImage is deallocated and why, the crash report refers to an attempt to use the UIImage after its release, so this would likely be in a different portion of your code.
If you have some suspect as to which class contain this UIImage, you can post some code so that we can help you inspect it.
As a hopefully useful hint as to how to reproduce this issue, I would also suggest sending the simulator a Memory Warning. Indeed, in such cases all UIViews that are not displayed are released and this could be the culprit with your UIImage. So, you send it and see if the crash happens again... just a hint, anyway...
My iphone app randomly received this message. I know certain it is memory release problem. However what is the best way to find which object leads this problem. Here are what I have tried
Use Instrument Leak and
ObjectAllocation Trace. Dont saw any
help to know which object have this
problem
Put NSZombieEnabled=YES and project executive ... Dont saw any
help either
Put NSLog everywhere but the EXE_BAD_ACCESS just appear anywhere.
in the debuger, just saw the code
happened in the assembly. like
objc-msg send.
review code many times and read memory management a lot time
and research online a lot time. but
no surprise.
Is there a completed solution to figure out this problem easily. I am a previous Visual C++ programmer, I deal with memory management with years and it is easy to debug and figure out in Visual C++.
If you couldn't see any helpful debug info, I would suggest you find all the places that you are doing a release. It is most likely the case that you have released something that did not need to be released. Code would help us in tracing the issue with you.
As Juan noted, the first stop is the Debugger - what does the debug window give for a stack trace when the app crashes? You should be able to see the line it crashed on... you said in a comment to one response that you saw the crash happen around the lines:
CGPDFDocumnetRef docA=CGPDFDocumentCreatWithURL(myurl);
CGPDFDocumnetRef docB=CGPDFDocumentCreatWithURL(myurl);
Are you really using the same URL object for both calls? Which line is it exactly?
It could be something around the way you make use of the CGPDFDocumentRef, you can find example code how Apple uses them in the QuartzDemo project, file "QuartzImageDrawing.m" (you can find the demo project from the developer portal or embedded in the iPhone documentation with XCode).
XCode is actually pretty powerful, but it does things differently from other IDE's.
In addition to Erich answer, I'd want to add go backward. Start with the most recently added release and work from there.
I ran in to this and it turned out I was releasing an auto-released object that was returned from a convenience method built in to the Cocoa-Touch framework. My problem was as Erich described -- I released this auto-released object. When the system attempted to release it, the program gave the error you are describing.
Regards,Frank
The best way to know what happend is using the xCode Debbuger, give it a try.
You will also receive the message when you don't pass enough parameters to a variable argument method. For example having a NSLog statement like this: NSLog(#"Hello %#");
To check what the error might be
Use NSZombieEnabled.
To activate the NSZombieEnabled facility in your application:
Choose Project > Edit Active Executable to open the executable Info window.
Click Arguments.
Click the add (+) button in the “Variables to be set in the environment” section.
Enter NSZombieEnabled in the Name column and YES in the Value column.
Make sure that the checkmark for the NSZombieEnabled entry is selected.
found this on iPhoneSDK
if set to on the NSZombie, it tells me that I'm releasing an object which is already released and gives me the memory address, very helpful... BUT I can't see which object it's... because the app stopped working...
any help?
thank you
You are looking for: malloc_history
http://www.friday.com/bbum/2010/01/10/using-malloc-to-debug-memory-misuse-in-cocoa/
malloc_history and my post on the same is certainly a correct answer and one way to do this.
However, it is quite likely you can do the same with Instruments, which is also going to be a bit less low level and more straightforward. Under Xcode's Run menu is Run With Performance Tool. Under that, you'll find Zombies.
Running with that, you should be able to see the type of the object being messaged and the retain/release event history.
Try Apple's http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Introduction/Introduction.html utility, found in /Developer/Applications/.
A commercial alternative is http://www.omnigroup.com/developer/omniobjectmeter/
This is driving me nuts. I just uploaded my first app to the App Store for the first time, and of course, now my app is exploding left and right. When I build with release build configuration, I randomly get an EXC_BAD_ACCESS after banging on the app for some variable amount of time. I turned Zombies back on, but the problem doesn't appear to be over-releasing a variable, as I don't get a message about sending a message to a released variable.
The error does always appear in the same spot in my code. It looks like I'm trying to retain a variable that hasn't been initialized properly. I haven't the slightest idea how I could be doing that.
But here's the weird thing: if I build in debug release configuration, IT NEVER CRASHES. I can bang on the thing all day long, and it's rock solid. I build with Release configuration, and it gets all intermittently crashy.
Looking at the Build settings in the two configurations, there aren't that many differences. In debug, the GCC 4.0 Optimization level is "None", while in Release, it's "Fastest, Smallest." If I switch the optimization level in Release to "None," the app behaves itself. Does anyone have a clue what I should be looking for to fix this? Alternately, how many bad things happen if I Distribute with No optimization?
UPDATE:
Dang! I really need a magic debug tool for memory errors. I've been working this problem for the last day or so. I added an exercise method that would reliably generate a crash and started looking for the area of code that was causing it.
The app would usually crash the 3rd-5th time I performed one particular type of operation. The only thing that was different about that type of operation was the value I returned from an accessory method. The accessory method generally returned NSDecimalNumbers with values of 0-3, but there was one special case when I was returning an NSDecimalNumber with a non-integer value. I would test the result of the accessory method looking for the non-integer value. I changed the special case to return an NSDecimalNumber with a value of -1 instead of the non-integer value, and I can no longer make the app crash.
Basically, the only change I made was switching from
[[NSNumber numberWithDouble:num] decimalValue] --> crash
to
[[NSNumber numberWithInteger:num] decimalValue] --> no crash
It's a little but more complicated than that, but not much.
Now, I'm happy that the app no longer crashes but the change I made does not fill me with confidence, as the old bits of code did not appear to be "broken" in any way. So, while my app doesn't crash anymore, it's not because I "fixed" it, I just changed some random thing and now it works. 8^(
UPDATE:
Debugger does not spit out a stack trace as it usually does when a program crashes. When it crashes, the debug console outputs the following:
Loading program into debugger…
[... copyright stuff...]
This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found).
warning: Unable to read symbols from "UIKit" (not yet mapped into memory).
warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found).
warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory).
Program loaded.
sharedlibrary apply-load-rules all
Attaching to program: `/Users/...', process 10066.
Re-enabling shared library breakpoint 1
Cannot access memory at address 0x4
Cannot access memory at address 0x4
(gdb)
If only it were as easy as turning on Zombies and you could always find your over-releases... There are lots of these kinds of errors that Zombies can't detect. There is no magic debug tool for memory errors; only careful programming (and there are patterns that make these errors much more uncommon, and much easier to debug when they do occur).
Optimized code can shake free lots of things that don't show up in unoptimized code. It does suggest slightly that it may be a local variable rather than an ivar, but perhaps not. It may just be timing; being faster may make a race condition go the other way more often.
If you can get it to crash, take a look of in the stack trace as a first step of course.
There's nothing deeply wrong with distributing without optimization, but it's just masking the problem. There's a coding error in there. Optimization isn't breaking your code. Your code is broken.
There's a good discussion of debugging memory problems here. The #1 rule is that you must use accessors. They will save you much heartache, so hopefully you already do this. I provide some other pointers in my short discussion of memory management rules.
I'd suggest cranking up the warning level on your compiler and see if anything pops up. Open up your project settings and enable every 'warning' option you can find. Or, find the project setting named Other C Flags and add the flags -Wall -Wextra.
You're going to get a LOT of white noise for things like signed/unsigned mismatches, possible loss of precision, etc., that you can (usually) safely ignore. However, there may be some key warnings that pop up that you definitely should NOT ignore: things like making a pointer from an integer without a cast (or vice-versa). If you're not 100% sure you can ignore the warning, fix the code so the warning goes away.
When over freeing a pointer you may see an error such as
"pointer being freed was not allocated"
When debugging with the simulator, I add a build argument MallocStackLogging = YES - this allows me to use malloc_history in the terminal to track down where I have over freed a pointer.
If I debug on the device with this build argument I get all sorts of console errors "cannot create stack log files" etc.
Oddly, I get some over freed pointer errors appearing on the device, but not on the simulator.
Has anyone had any experience tracking these down using the device itself?
Thanks!
Another way to do this. Make sure to turn NSZombie on so it reports the memory address of the object that is getting the extra release. Then Run with Performance Tool->Object Allocations. This will bring up instruments. Look at the Console log as provided by Xcode organizer. Once you get the crash lookup the memory address in instruments. You will see the entire history of mallocs/frees on that object, as well as links straight into your code.
I generally use NSZombie for such things, check this out
You need to set the MallocStackLogging env variables on the target executable...
To access these settings, select your executable from the Groups & Files pane in XCode, then Get Info.
Go to the Arguments tab and add the following entries into the “Variables to be set in the environment” box:
Please test the program for memory leaks,Also check autoreleases and whether you are releasing objects properly or not.Also we need to check whether a released object has a memory allocated or not.You also need to be careful regarding autorelease,because accidentally we might release an array or a string or any object that is already autoreleased...hope it helps and works!
Tip: You can test for leaks by analyzing your project(click shift+command+k)