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.
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.
I have brought back a root object from being encoded with NSCoder and have no idea how to memory manage this returned object. I have surrounded it with an autorelease pool, but the object doesn't go out with the pool. Code Here, See line 289 Line and code may change with Git Hub commits, but ultimately you will see the answer in working code, fingers crossed.
Since:
retainCount method is unpredictable, and
an autorelease pool doesn't remove the unretained object after being decoded, this article states decoded object are autoreleased and must be retained.
What is a guaranteed way to fully cause a deallocation of my decoded object?
You're managing memory returned from NSKeyedArchiver.
You either need to explicitly retain it, and call release when you are done, or use it immediately--such as write to file.
I recommend re-familiarizing yourself with the Memory Management Rules for Objective-C
Manual Memory Management is a bit tricky at first, but once you get the hang of the rules, it makes situations like this very easy to work through.
Now, if you need to ensure that the memory is removed immediately, you will need to write your own binary serializer that will follow the alloc:init pattern so the caller explicitly owns the memory. That way when you call release on the object, it will be deallocated.
NSCoder doesn't belong to that release pool.
thanks for viewing this post, it'd be great if you guys can help me out. I've been doing some objective-c and learned about the objective-c way of memory management, like making sure to call release whenever I own the object, when to call autorelease, etc. I also do not want to use ARC or the newly introduced GC because I like to manage my own memory, I plan to advance later on into iOS development, and I know it's a good practice to manage my own memory. But there's still one small detail that I seem to have hit a brick wall in. It has to do with sending objects the -retain message. I learned that sending the -retain message increments the reference count by 1. But would this be an appropriate time to send -retain? :
- (void) setName : (NSString* ) theName
{
// name is an instance variable of type NSString
[theName retain]; // Must release this
name = [theName copy]; // Must release this in dealloc
[theName release]; // decrement the reference count because of retain
}
Should I call retain here so that I own the argument temporarily and ensure it doesnt'
get released somehow before I get to use it?
Any help would be appreciated! Thanks!
No. You the object supplied as an argument to the method will generally be around until your method returns. You don't need the retain messages there. You copy the string here to keep it around after the method returns.
This is documented in Apple's Documentation on this page in the "Avoid Causing Deallocation of Objects You’re Using" Section. Specifically:
Cocoa’s ownership policy specifies that received objects should
typically remain valid throughout the scope of the calling method. It
should also be possible to return a received object from the current
scope without fear of it being released. It should not matter to your
application that the getter method of an object returns a cached
instance variable or a computed value. What matters is that the object
remains valid for the time you need it.
As an aside you really should consider using ARC. Its not good practise to manage your own memory. No matter how good one can be at managing their own memory the LLVM compiler is still better. Managing your own memory will lead to hard to troubleshoot issues caused only by yourself. It is an extra level of cognitive load that you really don't have to deal with and, when you finally let manual memory management go, you will breathe a sigh of relief at all the mental overhead you didn't even know was there.
I have an error that I can't understand, that is happening while I want to release all objects in an NSMutableDictionary.
It's happening for a custom object called body and the output is :
-[__NSTaggedDate body]: unrecognized selector sent to instance 0xffffffffffffffff
I found very poor informations about it on the Internet.
That's a private class of Apple. Errors like this usually occur when you mess up your memory management.
Why are you trying to release all objects in a dictionary? When you add an object to a dictionary (or an array), the dictionary will retain it (take ownership). And when you remove the object from the dictionary it will be released, you don't have to do that.
Did you already consider using ARC? It makes memory management a lot easier. You don't have to worry about retaining and releasing objects anymore.
It's an internal undocumented cocoa class. But you are not concerned with it as it's not really what's happening, it's a red herring that is probably happening for reasons that are complex to explain and irrelevant here.
Look at the reported address: 0xffffffffffffffff. That's a value that makes no sense. You should have got a segmentation fault, if it was not for that red herring.
You are for some reason sending the message body to an invalid pointer (maybe some corrupted data somewhere?).
Don't know this class, but it is probably a private class (my bet would be that it is a internal representation for NSDate objects that use the "tagged pointers" trick, but I'm just guessing).
Anyway your crash is happening not on an object called body, but when calling a method called body. And the crash is probably due to bad memory managment in your code that generates memory corruption
You should activate Zombies when running your app in debug to help you track over-released objects
You normally don't have to retain and release objects of an NSDictionary yourself, as container classes like NSArray and NSDictionary retain the objects they hold, and release them when the object is removed from them. So I don't see why you "want to release all objects in an NSMutableDictionary" : you only need to call removeAllObjects on that NSDictionary and you're done, no need to call release on the objects by yourself (neither do you need to call retain on the objects when adding them in the dictionary)
Whenever you try to set one data type to another data type like "if you directly assign an date component to text to an UIlabel" in this case I ll occurs
[toDateLabel setText:[tempArr lastObject]]; // Cause
[toDateLabel setText:[NSString stringWithFormat:#"%#",[tempArr lastObject]]]; // Solution