I've found that in my code i release object which had never been allocated and i do not get any error. The app doesn't crash. Everything works. I use Product -> Analyze and it tells me everything is all right.
I used to think releasing not allocated object leads to app crash. So my question is - should program crash when not allocated object is released (i.e I've missed something essential in my code which results in such a behavior) or everything runs as it is supposed to?
It all depends on if the pointer to the "unallocated" object is nil. In Objective-C, a message sent to nil does nothing. The app crash is caused by sending a message to a dangling pointer (or a garbage pointer etc).
If you haven't allocated the memory for your object, your object points to nil. When you call
[myobj release]
you're really sending the message to release to a nil object. Obj-C doesn't do anything in that case, and that's why your app doesn't crash.
Related
How can I check if object isn't deallocated on Objective-C?
The following standard condition checks only if object is initialized:
NSObject *objectVariable = nil;
...
if (objectVariable) {...}
You can't check after-the-fact whether an object is already deallocated or not, because it is invalid to do anything with an object that is deallocated (once an object is deallocated, any pointer that used to point to it is now an invalid pointer, and dereferencing it is undefined behavior). And since you don't know whether it is deallocated or not, and it may be deallocated, you cannot meaningfully examine it in any way. And a deallocated object may well "look like" a valid object if you try to examine it (it is undefined behavior, so any behavior is possible).
If this is an object of your own class, the obvious thing would be to print something or perform some other indicator action in the class's -dealloc method. That will tell you when it is deallocated.
Even if this is an object that is not of your own class, you may be able to either 1) add -dealloc as a category method, if the class doesn't override -dealloc, or 2) swizzle the -dealloc method, if the class does override it. Then you can print something in your version.
You can also profile it in Instruments; the Allocations instrument can tell you how many objects of a given class have been allocated, and how many are alive. If you suspect that you are losing track of objects or there is a retain cycle, the Leaks instrument may be able to tell you that.
I'm in agreement with the comments, If you're doing memory management right, there should be no need for such a check. Nor am I aware of such a check, if the address gets populated with a new object, the check would pass but could still crash your app.
My suggestions are to:
Read up on manual memory management rules, pay special attention to how blocks affect memory management, alloc/init methods, when to use assign, etc. Memory management rules should become second nature to you. Start with this Apple guide.
Run static analysis on your app and fix any memory errors. Fix all the errors really, these are bugs in your app. (CMD+Shift+B or Product->Analyze in the menu)
Reproduce the crash in Instruments using zombies. Read the retain/release report to find out where the object may have been over-released. (CMD+I or Product->Profile. Select Zombies in the window that appears)
Consider converting to ARC. Converting to ARC doesn't get you completely off the hook for understanding ObjC memory management, but it will take a lot of the burden off of you.
Coming from a java background, where everything goes under null pointer exception, I found some difficulties in understanding the difference between nil and deallocated instance in objective-c.
In objective-c it is known that sending a message to a nil object is not sorting any effect to the program flow.
However, sending a message to a deallocated object result in message to deallocated instance error.
In my ideal world a deallocated instance is 'nil', but obviously is not.
The precise question are:
what happens to the object when it is deallocated ?
If the object is deallocated, shouldn't it be freed, and then become nil ?
I think the problem is you have to differentiate between two things: objects and pointers to those objects.
The pointers are the ones that can be nil or not. And the objects are the ones that can be deallocated.
So sending a message through a nil pointer is ok. The Objective-C runtime is smart enough to keep program flow and just return 0. But if the object being pointed from that pointer is deallocated, then, there's something wrong with your program (you are deallocating an instance that still has some retain counts) and it should crash.
It frees allocated memory (deallocate it) and resources.
Not important. If you will not use pointer any more, than you can leave it as is.
Why is my object in the following leak trace doesn't get released?
The trace says its reference count is 0, so why doesn't it get released?
The object is a custom class that derives directly from NSObject. all I do with it is alloc it, init it, copy some strings/numbers from it, and send release, but still its considered a leak and doesn't get deallocated. I see it under allocations in instruments as 'living' so its really not deallocated. I create hundreds of these objects, so I cannot allow them to live.
How can I make this object get deallocated? why isn't it deallocated in the first place?
Well, it looks like you forgot to call [super dealloc] in your -dealloc method. We've all done that. :)
So the object is getting the dealloc call as you would expect, but isn't actually being deallocated.
I get this message. The thing is, I want to be able to tell cocoa to just not send the notification if the object no longer exists. Is there a way to do that?
The broader picture:
I'm sending requests to a server, but while that request is going on, maybe the user has done something to destroy the object expecting the request. When the response comes back, the object that requested it is no longer around, so I just want to have the notification center not handle the message.
Right now, I'm retaining the object when it requests a message, and releasing it when it receives the response. This way, I don't send messages to deallocated instances. But if it never gets the response, then it may not be freed, which leads to memory leaks. Hence my reasoning for trying to gracefully handle messages to deallocated instances.
Any ideas?
There is no "failing gracefully" when you message a deallocated object.
An allocated object is backed by a bit of memory allocated on the heap. It may have many references to that allocation; many pointers that contain the address of said allocation. When the object is deallocated, all those pointers are still pointing to it unless explicitly reset to some other value. And, of course, once de-allocated that bit o' memory can be re-allocated.
That is to say that, no, there is no magic -- no efficient magic anyway [see NSZombie] -- for turning all pointers to a particular object into something that magically eats all messages without error.
In other words, you need to architect your app such that objects that are no longer viable are really no longer viable across all layers of your app.
As bbum says, you can't send messages to deallocated objects. It's simply invalid. There isn't even such a thing as a "deallocated object" — once an object is deallocated, it's just gone. It's not a thing anymore and doesn't exist anywhere. Its old bit pattern might remain, or an unrelated object might be put in its place, or absolute garbage — that's where the crashes come from, not some magical "deallocated object" handler.
The correct thing to do if you don't want an object to be sent notifications anymore is just to unregister it from receiving them.
If the object no longer exists and you don't want it to crash on sending a message to garbage (that is, if you have a pointer to a deallocated object and you send that pointer a message, resulting in a nasty crash), if you want to avoid that, set your pointer to nil after you release it. This signifies you are done with the object. Sending messages to nil is perfectly acceptable, but sending messages to pointed-at-garbage is not.
[iVar release];
iVar = nil; // done with this reference.
Coming from Java and Python, I am not so well versed in memory management, but is there any way to find out what kind of object resides at a particular memory address?
I am asking because my application terminated with a cryptic message that reads:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSDecimalNumber encodedURLParameterString]: unrecognized selector sent to instance 0x164840'
and would like to get some clues as to what is going wrong.
And if that is not possible, some debugging techniques for such error messages would be greatly appreciated.
Thanks in advance!!
EDIT: Follow Up Concern (MOVED HERE)
After some investigation of the framework that I have been using, I came across something that I don't really understand.
If I have a method
- (void) myMethod:(NSString *)string {
[Object anothermethodWithString:string];
}
and I call
[Object myMethod:#"this is a string"];
Do I need to do something like
NSString *string2 = [[NSString alloc] initWithFormat:#"%#", string];
[Object anothermethodWithString:string2];
[string2 release];
instead of the way I had myMethod before? It seems like the string I passed through the parameter of my method got released somewhere, and doing that solves my problem. I guess I don't really understand what exactly #"string" does in terms of memory. Is it like an auto-released NSString?
well, from the error, the object type at that memory address is NSDecimalNumber. You got an error because you called encodedURLParameterString on a NSDecimalNumber which does not have a method with that name.
In gdb you could type
po <address>
to find out the object's description if it's really an Objective-C object.
But in your case it sounds more like you're sending message to an already deallocated object, which will give wrong result on the object's type. Try to enable NSZombie to show what kind of object it actually is.
This type of error is often caused by a "dangling pointer", the result of keeping a pointer reference to an object after it has been deallocated. If an other object is instantiated in the (now empty) memory space and you subsequently send a message through the dangling pointer, you get an error like that you've observed. This particular error is caused by sending a message encodedURLParameterString to an NSDecimalNumber.
The fact that the beginning of the struct objc_object of an NSDecimalNumber instance is in the memory location previously occupied by the object you think you're referencing isn't of much consequence. You really care about where the dangling reference is held, and why the object was deallocated before you expected. You can enable NSZombie tracking, which keeps deallocated objects alive and stops in the debugger when you try to send them a message. You can also investigate the stack trace from the site of the crash. The previous stack frame will likely point you to where the offending message was sent from, and thence to the reference that was used.
Once you've identified where the dangling reference is being kept, you should check whether that reference is correctly retained (to keep the object alive).