I have an, at least to me, strange case here: I have a relatively simple program which loads an XML file from the web, parses it and write the data into an array of dictionaries. Each dictionary represents a row in the table. The program works fine and if I attach my simulator to instruments and load the list, there is no memory leak.
Now here is the strange part: There is a button for the user to reload the list. If you press it, the previous data gets cleared, the XML newly downloaded and parsed and so on. If I press this button, I still can't find a memory leak. Yet if I press it twice, suddenly there are leaks all around. I am very puzzled, how come there are suddenly leaks where there used to be none before (The leaks only appear if the same code is run twice)? It is especially weird as I am using part of Apple's sample XMLParser for instance, my code is a 1:1 copy of theirs, yet when I run the parser twice, instruments reports a leak in this code.
I am glad for any help, I pretty much don't know how to got about this. The code should be fine. I have already tried "Build and Analyze", it does not reveil anything I would not see in instruments either.
All the best, Robin
There really isn't enough info here to make a solid answer.
That said, it sounds like you could be misinterpreting the results of the memory leak detection tool that you're using. If it is scanning the object graph looking for orphaned objects, it may not notice that an object is orphaned until you re-load. That's because there may be a static, cached reference to the root of the object graph in one of the 3rd-party libraries you're using (or in your own code.) Once you re-load, the cached reference is moved to the new root object and all the old objects are no longer referenced by any rooted variables (local variables on the call stack or static variables) and are therefore orphaned and "leaked".
The program works fine and if I attach
my simulator to instruments and load
the list, there is no memory leak.
That doesn't mean you have no leaks - instruments may not be catching them - it samples every n/seconds.
Related
I'm investigating a problem where it looks like our project is leaking file handles. Our application works for about five minutes but then after a while, low level file opening functions out and out fail. I can make the problem occur even faster if I manually leak file handles.
Our codebase is too complex for me to start manually debugging line by line to see what's going on, so I'm looking for some kind of debugging tool to help investigate this.
Any ideas?
Thanks
You should be using instruments to track any leaks. Any app you build you should really run it through instruments.
https://developer.apple.com/library/ios/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004652
Hint: profile your app using leaks and you should be able to trace any leaks.
re Instruments 'Memory Leak' profiling, do other tools give any more info re finding root cause of a leak?
My issue I'm stuck on is finding the root cause (as opposed to where the leaky object was created, which Instruments tells me). For an example where I'm stuck see What is the source of the leaky object for this code? Simplistically it seems I'm not releasing an object somewhere, but this object is bundled within a parent, which is within a parent etc etc so I'm having a hard time trying to track down where I went wrong.
So my question is, beyond Instruments (and the profiling using 'Memory Leaks', which tells you the location of creation of the leaky object, but not the root cause), are there any other tools I could run that could give me any more info than Instruments re tracking down the root cause point?
EDIT 1 - Note my application will BUILD & ANALYZE without any issues.
I'm fairly new to reading the instrumentation displays, but the way I found a couple of leaks in my app was to watch the allocated object counts in instruments and then repeatedly perform some simple UI function. I'd see 2 or 3 object counts constantly increasing over a period of time as I tapped the screen over and over.
Looking at the classes I found that during development I'd added some properties and forgotten to nil then in the dealloc code. Once I added those statements the leaks disappeared.
The interesting point is that these didn't show up in the leaks display or the static analysers. At least not that I recognised.
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
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.
Does Apple's Xcode development environment provide any tools for memory leak detection?
I am especially interested in tools that apply to the iPhone SDK. Currently my favourite platform for hobby programming projects
Documentations/tutorials for said tools would be very helpful.
There is one specifically called Leaks and like a previous poster said, the easiest way to run it is straight from Xcode:
run -> Start with Performance Tool -> Leaks
It seems very good at detecting memory leaks, and was easy for a Non-C Head like me to figure out.
Select Profile from the Product menu in Xcode 6 to launch Apple's Instruments tool. (The application is located inside the Xcode application's package contents: /Applications/Xcode.app/Contents/Applications/)
A commercial alternative is OmniObjectMeter. (Discontinued by The Omni Group)
The Clang Static Analyser is great for finding bugs in C, C++ and Objective-C code:
Here is the link for using instrument from xcode to detect memory leak/performance of you ios/mac application
Steps to run instrument from Xcode
You can run the tools within Xcode over menu -> run -> start with performance tool -> ...
Does Apple's Xcode development environment provide any tools for memory leak detection?
I am especially interested in tools that apply to the iPhone SDK.
Yes. Apple calls them "Instruments" (there's more than just memory tools).
See Apple's Introduction to Instruments User Guide. In particular, see Locating Memory Issues in Your App. It provides examples of how to use the memory-oriented trace templates.
ObjectAlloc and MallocDebug should both be of help to you. If you installed the entire SDK, they will be found in Developer->Applications->Performance Tools.
Their names give you a pretty good clue as to their functions, OA, tracks the objects create and MA is a general memory leak tool.
I haven't tried them with iPhone development yet, but I have to believe that they would work there as well.
Assuming you have registered for ADC iPhone developer site, here the link to follow:Instruments User Guide
When using rustyshelf's solution make sure you test on the iPhone and not on the simulator. Memory usage is dramatically different.
Made a sum up of the main memory leak tools: iphone-essential-performance-tools-list
Step 1. Pick the Allocations instrument
Choose the profiling template for Allocations:
On the main Instruments interface, click VM Tracker, if present, and press the Delete key since you won't be needing that particular instrument:
By clicking the plus button in the top right, you can add more instruments for different kinds of testing, but I won't be covering them in this tutorial.
Step 2. Set up your Instruments settings
Before running any analysis, there are a few things you need to do. First, you need to plug in an iOS device that has your app installed on it. It must be a physical device because the iOS Simulator is still a simulator and may not accurately represent memory use in your app or how an app might perform under memory pressure.
To pick your target, click My Computer near the top, hover over your device, and then pick your app from the sub-menu:
Next, there is a panel where you can alter the settings for the types of allocations you will be viewing. Besides making sure the Created & Persistent bubble is checked, there is not much you need to do beforehand.
Step 3. Press record to run the instrument
Once you press the Record button in the top left, your app will start up on your device, and Instruments will begin to chart your allocations. All you need to do here is run through your app, focusing on possible problem areas to see if more memory allocates than deallocates. This could mean doing a lot of repetitive tasks, but you'll thank yourself later.
You should see something like this:
I recommend running through your app once and getting to a stable point in memory so you have a good baseline that will make any increase noticeable. When you are satisfied you have enough data to test, press the stop button in the top left.
Step 4. Analyze
The first thing I do is set my inspection range to measure the total persistent bytes at my baseline. That persistent byte number is located right under the allocation summary.
To actually set the inspection range, use the keyboard shortcut Command < for the left inspection range and Command > for the right inspection range. In our app, we have a baseline of about 20MB.
Then, I move my right inspection range to a point where I had run through the app again and came back to our root. Here, you can see memory is about the same. So, by doing this a few more times and seeing your memory come back to our baseline, you can assume there are no major memory issues.
There are different ways to analyze this data that I won't cover here, but be aware that there's a whole drop-down menu of ways to view and analyze your data.
Step 5. Marking generations
If you prefer not to deal with the inspection ranges as much, there is a feature called Mark Generation. There is a button for it on the right panel of instruments.
This button will mark points on the timeline of instruments based on where the inspection line is. It does this in order to keep track of all the allocations since the previous mark, or from the beginning if there are no other marks. You can mark generations as you are running the allocations instrument or after you have stopped the run, as in this example:
Step 6. Check out the stack trace
The last thing to cover is looking at the stack trace. For this, you want to set your inspection range to highlight all the allocations, and then look at the statistics view, making sure the Created & Persistent bubble is selected on the right panel. In the statistics view, make sure Persistent Bytes is sorted from highest to lowest. There are a lot of allocations here, and it can be hard to understand what is going on, since a lot of them are system allocations.
Going deep
Look at the largest allocations and click on the right-facing arrow. A lot of times there will be allocations inside the ones you clicked on and many of them won't have meaning to you.
As you highlight different allocations after clicking an arrow, continue looking at the extended detail on the right panel. Eventually you will come across some bold text that leads to actual code in your project, telling you what the issue might be.
If you double-click one of the bold items in the stack trace, it will take you to the actual code (assuming you ran allocations on an app you own).
There are a lot of useful things about this view, one being the mostly yellow tags on the right showing you just how much memory each method call is taking up. Every app is different so you, the developer, have to decide if the highlighted method is a problem, something you can optimize, or just an unavoidable part of your app.
In my case, that UIColor variable is something that is persistent and used throughout our app and is therefore, acceptable throughout the life of our app.
found here
Try this one also, a simple tutorial to start with Xcode insturments
Memory leak tool: http://www.raywenderlich.com/2696/
Basic: http://www.raywenderlich.com/23037/how-to-use-instruments-in-xcode