I appear to have some overzealous releasing going on in my obj-C app - getting error message
"-[myobj release]: message sent to deallocated instance 0x5633b0"
. I know the class of the object instance causing the problem, but this class is used all over to create many instances.
My thought is I could put some logging in the init method of the class to log whatever "0x5633b0" corresponds to which should help me track down where the instance is being created.
What exactly is the "0x5633b0" and is there any way I can get access to that value in the code to log it?
Thanks.
What worked best for me when I ran into similar problems recently was the following:
Under under Project->Edit Active Executable -> Arguments tab -> Environment variables section I added and set to YES the following variables: NSAutoreleaseFreedObjectCheckEnabled, NSZombieEnabled and NSDebugEnabled.
Under the Run menu, I selected Enable Guard Malloc.
With these settings the debugger provided more hints on what's wrong with my code.
(I found these tips here)
Good luck,
Ori
0x5633b0 is likely the address of object in question (the value of self). You can use NSLog or printf with %p to print it.
0x5633b0 is likely the address of the deallocated object (the value of myobj). You can use NSLog or printf with %p to print it.
You can also use the instruments profiler to find the deallocated object.
1. Start the profiler:
2. Select the "Zombies" and start the profiler.
3. Click through the simulator until you hit your "deallocated error case"
In the debugger, type info symbol 0x5633b0 and you'll get some indication as to what object it is. One other thing that might be helpful is backtrace which will give you a stack trace. All in all, this blog entry has some great tips.
you can also add these to environment variables:
MallocStackLoggingNoCompact 1
and write in the gdb console:
info malloc-history <paste-address-here>
Reference: here
Consider using the NSZombieEnabled flag.
You will then know what is this deallocated object you're sending a message.
You're not managing your memory properly -- you're calling release/autorelease on some object more times than you're calling retain. Make sure you're following all of the rules laid out in the Memory Management Programming Guide for Cocoa.
0x5633b0 is just the address of the memory location at which the object is stored. One thing you can try to do is to add some code to the init method:
- (void) init
{
if(self == (MyClass*)0x5633b0)
NSLog(#"Allocated object at address 0x5633b0"); // put a breakpoint on this line
// do rest of init...
}
If you have any other init methods (e.g. initWithCoder:, which is called for objects instantiated from a XIB), make sure to put this snippet in those methods as well. Put a breakpoint on the NSLog line, and then see when it gets hit. Note that it may get hit several times, if an object is allocated at that address, deallocated, and then another object happens to be reallocated at the same address. The last hit before the crash is the one you want.
Related
I have problem with Thread 1: EXC_BAD_ACCESS (code=1, address=0xf00000c) and I don't know how to resolve it.
It appeared when I change some object in core date and save it and I try to pop this controller to parent.
This error is in main() with retVal.
here is some code
int retVal;
#try {
retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
*/\ error is here**
}
#catch (NSException *exception) {
NSLog(#"%#", [exception callStackSymbols]);
#throw exception;
}
return retVal;
After re-runing app all my changes are in core data. What is more this problem is only on iOS 7. iOS 6.1 is ok.
Does someone have idea how to resolve it?
As a comment said this error is likely to be deep in your code. If the culprit is a zombie, the easiest way to find it is to run it (preferably in the latest Xcode, currently Xcode 5, as it has been improved) in profiler and choose "Zombies". When it fails, you can see the history of everything that has happened to the object.
Also, set an exception breakpoint. You may get a break when the error happens instead of in main, where the exception gets passed up.
I just had the exact same problem.
Looked here and found nothing so I started backtracking until I thought, maybe I should try Clean Build Folderđ¤
I was glad it was as easy as CLEAN BUILD FOLDER!!!
Product- Clean Build Folder(⧠â K)
đ
I resolved this problem with "Zombies" and the problem was with
[UIScrollView(UIScrollViewInternal) _notifyDidScroll]
I added
- (void)dealloc {
self.tableView.delegate = nil;
}
This problem was only in iOS 7.
Thanks for help!
I have resolve this issue only by debugging the source code and re-analyze my logic.
Below are some reference that help me lot.
EXC_BAD_ACCESS means that message was sent to a point in the memory where thereâs no instance of a class to execute it. Thus âbad accessâ.
You will get EXC_BAD_ACCESS in 3 cases:
An object is not initialized
An object is already released
Something else that is not very likely to happen
Thatâs already a good starting point. Start using the debugger, if you recently added a new object to the class youâre working on, put a breakpoint at the line before the freshly added object is used for the first time and check the values in the debugger.
Whatâs happening most though is that you will be sending a message to an overreleased object â i.e. object that is gone from the call stack. In this cases everything (and indeed everything) you will get in the console will be just :EXC_BAD_ACCESS
This is because the object is gone, there is no information what class was it, or what source file or anything else.
Please try to avoid using zombies for this.
EXC_BAD_ACCESS means there is no instance of a class to execute it.
There are 2 or more possibilities:
An object is not initialized
An object is already released
Please debug application carefully and analyze each object carefully. That might solve your issue.
I solved the same problem by finding out that the name of one of my NSString variables had the same name as one of the frameworks' class variables. Took seconds to change the name a little and problem disappeared.
With such a huge number of class variables in frameworks, it is very likely that once in a while, every programmer just by coincidence names some variable in his class exactly the same as one used somewhere in framework classes.
So it doesn't have to be Xcode bug in most cases.
In my case, I was using third-party library and I forgot to set custom-class name in Storyboard Identity Inspector
And there may be another issue which I faced today:
I had a mutable dictionary with a non-object entry try. There was a code snippet with adding a BOOL value to the dictionary. So no wonder that I got this error =).
In my case it was trying to log an Int32 with %s in print statement
in my view this is the equivalent of every other language NullPointerException,
but unlike other languages there are no hellping pointers (class name / method or line of the occurrence / god forbid a Stacktrace),
so the only thing i could do to solve it fast is to start printing main functions and views, (a very primitive solution),
create a swift: Debug.swift
add this function into Debug.swift:
public func trace(_ message: String = "", file: String = #file, function: String = #function, line: Int = #line)
{
print("**** \(file).\(function)[\(line)]: \(message)")
}
then you can use it like this:
trace("initializing")
to use it inside a var do this:
let _ = trace("initializing")
this should print something similar to this:
**** /path/to/my/file/MyFile.swift.someFunc()[18]: initializing
this is how i started adding debug lines to gain some flow record, so next time i have a EXC_BAD_ACCESS i will have a clue where the problem leis
don't forget to disable the prints during production deployment
I have a NSManagedObject which I'm trying to instantiate with given values. I access the setters like so:
object.couchID = (NSString *)[dictObject objectForKey:#"_id"];
...and this works fine on my machine, but my partner gets this error when he runs it on his machine:
'-[NSCFString type]: unrecognized selector sent to instance 0x4e465e0'
About 90% of the setters (all formatted in the same way) work on my partner's machine, but a good 10% fail with that error. All of them work on my machine.
We're running the exact same code (according to SVN (yes, I know)), and fetching the same data from the same server, so everything seems like it should work.
We've checked the objects being passed, and they're the same. Commenting out the setter allows the code to get through to the next troublesome setter, but of course we need it to actually work. How else should we troubleshoot? Thanks in advance.
Update 1: Unlocked the Tumbleweed badge for that one... guess it's too sticky to touch? Any thoughts or guesses are welcome. And hey, you could earn 50 points.*
Update 2: the mixed-good-news is that checking out a fresh version from source control results in the same problem on my machine, so a) it's definitely something in the code, and b) I can more actively troubleshoot. Thanks for all your suggestions so far, I'm going to go through them all again.
I ran into something similar at work the other day. I suspect that one of you has a stale .momd file inside the app bundle, and that it's not being replaced when it gets upgraded. I suspect this is a bug in Xcode 4, though I haven't totally verified it yet. If your partner deletes the app completely and then installs the app, does the error go away?
You may need to create a temporary variable whose value is object cast to whatever the actual class is, e.g.
MyClass *c = (MyClass *)object; // if object is in fact a MyClass instance
c.couchID = (NSString *)[dictObject objectForKey:#"_id"];
I have seen cases where the compiler cannot make mental leap and realize that your attribute is the class you know it is. The solution for me in these cases has been to be more explicit. Does this make sense? It's worth a shot at least, no? :-)
if this code fails on your partner's machine:
someManagedObject.couchID = #"some hardcoded string";
seems like you have a dangling pointer: i would check that someManagedObject is properly retained and still a valid object when you try to call the -setCouchID method on it.
I have had nearly the same problem when trying to draw a CATiledLayer with data in NSManagedObjects. What should be a valid object barfs with an "unrecognised selector" exception
It nearly always happens because theres no retain on the object external to the point where you are trying to set or get the property. Being in a separate thread seemed to have a relationship too.
After fruitlessly trying to get round this with [NSManagedObjectContext lock] and retain on the context within the new thread I eventually just threw the contents of my fetch into a mutable set to try and keep a grip on it which seems to work on iOS but not on OS X so well.
So a couple of possibilities
Are you doing this not in the main
thread and does the MOC have a retain
within that thread. Check the docs
for [NSManagedObjectContext lock]. But essentially each thread working with the context needs its own retain on the context.
Try throwing it into a container
while you operate on it. Make it a
bit stickier. Sorry if that sounds
like voodoo but it is.
Recently I was repairing someone's code. There was a big class that would not dealloc. You'd have to hit it with 5 or 6 releases to get it to dealloc.
I carefully looked through the big class and eventually found the various things that needed to be released.
This got me thinking: there just has to be some really easy way to "find" all the retains on an object .. am I right?
So, is there a simple way to "find all the retains" on an object? Is there a button in XCode or Instruments that everyone else knows about?
What do you do when you can't find a mystery retain like that?
So in the iOS universe, if anyone knows the "Show where all the retains came from on this object" button -- thanks!
P.S. Note that there is no leak, and this question is totally unrelated to leaks. The object simply "perfectly correctly" wouldn't release.
Later ..
Truly astounding solution by Fabio:
Fabio has provided an astounding solution to this problem. In nine words, here it is:
-(id)retain
{
NSLog(#"%#", [NSThread callStackSymbols]);
return ([super retain]);
}
That is amazingly useful in many situations and leads to many other useful things. You've probably saved me two man-weeks of work per annum forever, Fabio. Thanks!
BTW if you're just getting to grips with this and struggling with the output, I saw that typically there will be many chunks featuring "UINib instantiateWithOwner:". It looks like those will come first, the significant chunks will follow.
Instruments can show you the call stack for every malloc, release, and retain for any Obj-C object in your app with no code changes required. It works when you're using ARC, which is not the case for the solution from fabio.
It's really useful for finding those mystery retains - e.g. when an object just won't dealloc when it should.
Here's how:
CMD + I (Product / Profile)
When Instruments pops up choose 'Allocations' (NOT Leaks)
Your app should run.
Do whatever causes your mystery retains to happen.
Select the 'Allocation' instrument on the left-hand panel.
Press CMD + 1 or select the circle with the wave in it on the right. In the panel on the lower right, tick the 'Record reference counts' option. This is important, or only mallocs and frees will be recorded.
In the search box on the top-right of the list, type the name of your class (e.g. BCMyObject).
This filters the list of 'Statistics' to show how many instances of your class are currently live. The #Persistent column shows how many instances are live.
Click the row, and then the little arrow -> next to the class name. You'll see the breadcrumbs shows 'Statistics > Allocation Summary > BCMyobject'
This shows you all the instances of said class (and which ones are live).
Select an instance, and click the arrow again (this time by address)
Now you'll see 'Statistics > Allocation Summary > BCMyObject > History: 0xADDRESS' in the breadcrumps.
This'll list every time the object is malloc'd retained or released.
Now in the left panel where the 'Record Reference Counts' option was, press the icon that looks like a bar with boxes connected to it or press CMD + 3.
Select one of the rows and you'll see the complete call stack that led to the call.
Easy! (ish)
Just guessing... but you may overwrite the retain method of the custom class calling super and throwing a nice NSLog to print the call stack.
Update with the actual code from Joe
-(id) retain {
NSLog(#"%#", [NSThread callStackSymbols]);
return ([super retain]);
}
Another important detail is that [NSThread callStackSymbols] returns a NSArray of NSStrings that can be filtered and used for other purposes. For example in complex and dynamic code, to check if a method properly causes another one to fire.
NOTE:
In an ARC environment you will need to first add the -fno-objc-arc to compiler flags to allow you to override retain and call super.
Place a breakpoint on custom class' retain
You could set a symbolic breakpoint on retain and then set it to the retain method of the custom class. The problem here is that retain is a method on NSObject so you will get the choice of all objective-c classes when placing the breakpoint.
In this case it would be better to overwrite the retain method of the custom class with a call to super, so it would not do anything but you could then place a breakpoint in it.
Use a breakpoint action to log the caller
To add a breakpoint action double click on the blue marker. Find the breakpoint in the list and press the + button on the right. Then choose Debugger command and add the GDB command frame 1 in this field, which will show you the caller of the retain. By this you cold log all retains and where they come from. When logging the releases in a similar way you could check what was the extra release.
It is still a bit tedious, but this is the best I can think of.
Instruments and its memory management stuff is your friend. Leaks and Zombies are two of the most valuable tools available. Use them.
Product -> Profile (or Cmd-I)
It is, unfortunately, not easily possible to programmatically determine what "owns" an object, since the idea of "object ownership" is a coding convention (unless you enable garbage collection).
Stack logging is often useful (I usually use a few breakpoints with bt;continue) but that only tells you the function that called retain, not the "bigger picture" (e.g. you might "transfer ownership" with [ivar2 release]; ivar2 = ivar1; ivar1 = nil;). Sometimes it's a UIKit leak so you don't have the source code and you really have to go digging.
If it's not a leak, however, call -release a few times and see where it crashes!
Have you try using "Build & Analyse" in Xcode?
It's great for getting the bottom of objects not being released.
Example: I have a view controller and get rid of it. But there's still an variable holding it's memory address. Accessing that results in EXEC_BAD_ACCESS. Of course. But: Is there any way to check if that variable is still valid? i.e. if it's still pointing to something that exists in memory?
You need to read this again:
Cocoa Memory Management Guidelines
In short, if you want something to stick around you must retain it.
If you want something to go away and you have previously retained it, you must release or autorelease it.
You must never call dealloc directly (except [super dealloc]; at the end of every one of your dealloc methods).
You must never release or autorelease an object that you did not retain.
Note that some methods do return retained objects that you must release. If you alloc an instance of a class, that implies a retain. If you copy and instance, the copy is retained.
If you are ever tempted to use the retainCount method, don't. It isn't useful. Only consider retain counts as a delta; if you add, you must subtract, but the absolute value is an implementation detail that should be ignored.
(In other words, even if there were ways to check for an object's validity definitively -- there aren't -- it would be the wrong answer.)
Oh, and use the Build and Analyze feature in Xcode. It does a very good -- but not quite perfect -- job of identifying memory management problems, amongst other things.
That's what the entire memory management model is set up for - if you call retain at the right times, and release and autorelease at the right times, that can't happen. You can use NSZombie to help you debug.
Use "NSZombieEnabled" break point.
For this reason only all strongly recommend us to use accessors. If your object is released anywhere, it will get assigned to nil, and there will be no harm if you call any API or method on Nil object. So please make a habit of using Accessors.
you just add this NSZombieEnabled Flag as an argument to your application in build settings. and enable it. Now you run your application in debug mode. If any such crash is about to occur, this breakpoint will show you which object is freed and where it is crashing.
Cheers,
Manjunath
If by variable, you mean whether the pointer to your object still references valid memory then:
MyClass *myVariable = [[MyClass alloc] init];
//Tons of stuff happens...
if (myVariable != nil)
//Do more stuff
I have an app that appears to run without problems in normal use. The Clang Static Analyzer reports no problems either. When I try to run it in Instruments, it fails with an unrecognized selector exception.
The offending line is a simple property setter of the form:
self.bar = baz;
To figure out what's going on, I added an NSLog() call immediately above it:
NSLog(#"class = %# responds = %d", [self class], [self respondsToSelector:#selector(setBar:)]);
self.bar = baz;
On the emulator (without Instruments) and on a device, this shows exactly what I'd expect:
class = Foo responds = 1
When running under Instruments, I get:
class = Foo responds = 0
I'm stumped as to what could cause this. Perhaps a different memory location is getting tromped on when it's in the Instruments environment? Can anyone suggest how I might debug this?
If bar belongs to self, can't you do bar=baz; ?
Check your properties.
Perhaps to you need a cast on baz?
There's not enough information here to know what's going on, but then, if you knew what information to provide you'd probably have already fixed it. So. A few things to check:
Is the "self" pointer being swizzled in any way? Try printing out the value of self at various points just for sanity's sake
When your code runs in Instruments, is it running in a different mode? (32-bit vs. 64-bit, Garbage collected vs. Retain-Release, etc.) I'm not sure why any of those would have an effect, but if it's running in a different mode, that's something to look into.
Are you synthesizing the setter correctly? Or is it being provided dynamically (via Core Data, etc.)? If you manually specify a setBar: method, do you still get the error?