Deallocated instance and nil object in objective-c - objective-c

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.

Related

Potential Leak of Object stored into a NSMutable dictionary (GPUImageFramework) iOS 8+

I am new to Objective C, and I would really appreciate any help resolving a memory leak. I am trying to resolve memory management issues that occur in the GPUImageFramework.
In the method below I am getting the following messages highlighted in blue:
Method returns an Objective-C object with a +1 retain count
Object leaked: allocated object is not referenced later in this execution path and has a retain count of+1
-(void)setAndExecuteUniformStateCallbackAtIndex:(GLint)uniform forProgram:(GLProgram *)shaderProgram toBlock:(dispatch_block_t)uniformStateBlock;
{
[uniformStateRestorationBlocks setObject:[uniformStateBlock copy] forKey:[NSNumber numberWithInt:uniform]];
uniformStateBlock();
}
enter image description here
I take it that the method being stored in the NSMutable dictionary needs to be released into memory.
Please can somebody point me in the right direction?
I have ARC enabled within the GPUImageFramework
You either need to enable it for your project, not just for the framework, or you need to handle memory management manually.
The sub-expression [uniformStateBlock copy] returns an object with, in the language of the error, "+1 retain count"; i.e. an object the caller "owns" and which the caller must release.
When your code inserts an object into the array the array itself also takes ownership, i.e. does a retain. It does not take ownership from the caller, it is still left owning the block returned by copy and it is this ownership which is never relinquished which results in the leak, as the error states.
If you enable ARC it will take care of this and release the callers ownership of the block at the appropriate point.
Otherwise you can leave ARC off and insert a release call when the caller no longer requires the block (which still leaves the array with ownership).
HTH

How can I check if object isn't deallocated on Objective-C?

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.

After ARC, in what ways you can still refer to a deallocated object by mistake?

Is it still possible? I mean weak pointers are automatically nulled. Strong pointers only deallocate when pointed somewhere else.
Can we still have an error of pointing to deallocated objects?
__unsafe_unretained is done by those that knows what they're doing. So it's not really by mistake.
Beware of __autoreleasing vs #autoreleasepool. The compiler isn't smart enough to retain the __autoreleasing variable's value when it drains the autorelease pool. This includes #autoreleasepool inside a method with an NSError** parameter.
Beware of __block __autoreleasing variables. This includes a block object that sets an NSError** variable. Some block-based API wraps the block call in an autorelease pool, so you end up with the same flaw as above.
Beware of API that is effectively unsafe-unretained. For example, many delegate pointers in AppKit and UIKit are unsafe-unretained, not zeroing-weak. If you arrange your object graph incorrectly then you'll crash when the delegate object is deallocated and the kit tries to use it.
Beware of heap-allocated C arrays of object pointers. It is possible to do it correctly, but if you're not careful then you get leaks or crashes.
Beware of thread races. If you have a multithreading bug then all bets are off.
__unsafe_unretained, CFTypeRefs, malloc()ed memory

Releasing object which is not allocated without any error

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.

Messages to deallocated instance - failing gracefully

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.