-1

Consider the following snippet illustrating the problem of object destruction during method execution.

-(void)handleNotification:(id)notification{
    //owner has reference so this is fine
    self.foo += 1;
    //call back to the owner/delegate, owner may set reference to nil
    [self.delegate didFinish];

    //if object has been dealloc'ed, it crashes
    self.bar += 1; // CRASH
}

Actually, I cannot even reproduce the crash, because it only happens rarely, but I know it exists from Crashlytics reports.

I am trying to fix it by declaring a strong reference to self:

-(void)handleNotification:(id)notification{

    self.foo += 1;

    MyObj *strongSelf = self;
    [self.delegate didFinish];

    strongSelf.bar += 1;
}

However I am not sure if it correct (as I said, I cannot reproduce it and check that crash has gone). If this fix correct? Will this change guarantee that self will not be destructed until end of the method?

Nick
  • 3,205
  • 9
  • 57
  • 108
  • What is `didFinish` supposed to do? If it is allowed to dispose `self`, `didFinish` should be the last statement of the method. – Willeke Oct 31 '17 at 14:07
  • `self` will not be released until it actively executes, so the actual first scenario is not actually even possible to happen at all, unless you are messing with different threads in `-didFinish` uncontrollably – what is your crash log about actually? how does your workflow looks? when do you unsubscribe from the notification-center? – holex Oct 31 '17 at 16:34
  • @holex Your statement ("self will not be released until it actively executes") is correct only if `self` is a `__strong` reference. However, Objective-C does no give any guarantee about it. – Nick Oct 31 '17 at 16:50
  • @Nick, an object is not going to be released while it currently executes, even if there is __no reference__ to it; opposite behaviour would lead to a massive chaos. – holex Oct 31 '17 at 16:54
  • @holex I used to think so until I bumped into this crash. Unfortunately, there is no any benevolent almighty magician who checks if something is "currently executing" or not. See https://stackoverflow.com/questions/17996516/is-self-weak-within-a-method-in-arc for details - you will not regret. – Nick Oct 31 '17 at 17:09
  • @Nick, I appreciate you trying to convince me about how __not__ an OS works; but unfortunately the OS works on its own way, there are many rules there: one of them is about not releasing any memory what occupied by an object which executes commands on any thread. no need to thank me for the intel, but I hope you understand eventually why your first scenario is completely __impossible__ to happen in any modern OS, including iOS / OSX. your problem is originated somehwere else, so, go back to my questions and commence updating your OP with details, please. – holex Oct 31 '17 at 19:47
  • @holex Official Apple docs says: "The self parameter variable of an Objective-C method is never actually retained by the implementation. It is undefined behavior, or at least dangerous, to cause an object to be deallocated during a message send to that object". From this statement clearly follows that: 1) it is possible to deallocate an object 2) it is dangerous. My question was not about if it's possible or not. It is possible as explained in https://stackoverflow.com/questions/17996516/is-self-weak-within-a-method-in-arc. I only was interested how to defend against it. – Nick Oct 31 '17 at 22:11
  • @Nick, I don't want to actually argue about that, but you may need to start breathing slowly and comprihend the following part of the quoted statement word-by-word: _"(...) during a message send to that object."_ your scenario is far away from this sutuation, as matter of fact it could not be actually further than currently is – so, let's go back to the basics third time again: __your object is not going to be deallocated until it executes__, and finally accept this simple fact and start focusing on the questions I have raised? there would be a little chance for you to get some actual help. – holex Nov 01 '17 at 08:28
  • @holex "during a message send to that object" is exactly what happens.` handleNotification` is a message. and `self` is an object. Also, can you please tell me where this statement "your object is not going to be deallocated until it executes" comes from? What official doc contains such a statement? – Nick Nov 01 '17 at 09:21
  • @Nick, yet you are not actually understand your own quote nor comprehend how modern operating system works. there are many nice books in any uni's library about operating systems' brains and it is more than obvious that your method does not exhausts the condition _"(...) during a message send to that object."_ at all, as you are __not__ sending any message _to_ `self` but _from_ only, according to your snippets at least. anyway. good luck to find your solutions. I don't have more time to waste honestly :( I'm sorry. – holex Nov 01 '17 at 09:33

1 Answers1

1

I don't think making such reference is a good idea/practice, it would impact the performance of your application.

More info here

Furthermore, I'm guessing that the caller of your method is the NSNotificationCenter and it does not retain the observer.

bubu
  • 333
  • 2
  • 9