Prevent EXC_BAD_ACCESS during backgrounding for long running processes - ios

In my application, I have a series of long running processes. Sometimes, when the app gets backgrounded, one of these processes will return and try to notify other objects (which have been released) that it has completed, causing an EXC_BAD_ACCESS. Something like:
[process runForALongTimeWithCompletion:^(){
[possiblyReleasedObject heyTheProcessFinished];
}];
How can I check if possiblyReleasedObject has been released? Or, more precisely in my case, how do I check if it is dereference-able, such that referring to it won't cause a EXC_BAD_ACCESS error?

There is no way to (safely) check if a pointer to an object points to a valid memory location in Objective-C. You'll need to structure your program such that objects holding a pointer to possiblyReleasedObject retain it so that it doesn't get inadvertently released.
When an object holding a pointer to possiblyReleasedObject no longer needs it, it's generally good practice to set the pointer to nil after calling release in order to avoid accidentally dereferencing a bad pointer.

Related

Can we use deinitialized variables in code, or are they pretty much useless because they are deallocated right after?

Im a little confused on the topic of deallocation when comparing it to deinitaizlization. Doesn't deallocation happen the moment after a variable is deinitialized.....My main point here is, Could we use/manipulate deinitialized variables somehow? or they are pretty much useless because deallocation takes place right after...?
In Swift the deinit method is called as part of the deallocation process. Precisely when the memory allocated to an object is released you cannot know, but you can't access the object after it has been deinitalised.
Aside from it not making any sense to do so, it isn't possible to manipulate the object after deinit since the deallocation process is initiated by the removal of the last strong reference to the object. as there are no references how could you manipulate the object anyway. (I suppose you could use an unowned/unsafe reference to attempt to access the object but this would result in your app crashing)

Why is an object not automatically set to nil when its reference count becomes 0?

In a non ARC Objective C environment, I understand why we have to release an object: to free the memory allocated for it; I understand why we have to set it to nil afterwards (if we are sure nothing else needs the instance / nothing else still has a hold on the object): to avoid dangling pointers.
However my question is, if all objects release their hold on an object, "carInstance" for example, resulting in its reference count going down to 0, why oh why does that Not automatically make it nil?
If reference count is now 0, is the object still usable in any way? Or is this just one of those things we have to do just because that's how not having garbage collection works (can't be, there must be a reason)
The simple answer is that the manual memory management model that was used pre-ARC is lightweight and simple. The behavior you are wishing for is the behavior you get with weak pointers under ARC; and it requires extra work by the OS, to track weak pointers and nil them out when the object is reclaimed. It's doable, clearly, but the cost of implementing it, as well as the computational overhead, wasn't deemed worthwhile until Apple was already rolling out the extra work of implementing ARC.
After an object is deallocated, the dangling pointer is worse than useless: it is downright dangerous. Referencing it while it points to unallocated memory produces an exception; referencing it after it is randomly reassigned to another object or some other memory allocation will typically produce an 'object does not respond to selector' error.

Apple Instruments - Reference Counting

I'm having trouble understanding what's happening here. I am debugging an app because I think it's retaining a class 'DownloadController' after its been used. Using ARC, it should automatically release the object when the Reference Count is zero.
So in instruments it looks like
From that I assume, that 48 bytes have are still 'live' and being used, correct?
So I try to find what is causing this object to be retained, when its no longer needed, by using reference count traces.
At the bottom it says, RefCt is zero; so why has the object not been released? How can I debug further, why it hasn't been released?
These ARC anomilies were being caused by NSZombieEnabled, after removing this argument it started freeing objects.

Keeping a strong pointer to a local object

I encountered this thing in a book which I am reading and it got me thinking:
"When you allocate a block, it is created on the stack. This means that, even if you were to keep a strong reference to it, calling it later would result in a crash because the memory would be destroyed as soon as you leave the method in which it was defined."
I thought if I have a strong pointer to something, it is kept alive?
Does this mean this does not apply for objects allocated on the stack?
I am trying to think of an example without using blocks...(e.g., of pointer - maybe an ivar- pointing to a stack allocated object which gets destroyed even though the pointer is alive)
Objects are never allocated on the stack in Objective-C. Blocks are special however, since they are stack allocated. So if you want to retain a pointer to a block, you must first copy it by using Block_copy and use the copy, then release it with Block_release. This must be done if the block is to be used after the scope it was declared in is destroyed. More on the matter here: https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/Blocks/Articles/bxUsing.html (under "Copying Blocks"). Yet again though, this does not apply to regular objects.
Blocks can be messaged like objects. To move them from the stack to the heap, just "copy" them.
void (^stackBlock)() = [^(){
NSLog(#"Hello world");
} copy];

[__NSCFString count]: unrecognized selector sent to instance 0x75bc230'

My code is:
SCDownloadManagerView *downLoadMnger = [[SCDownloadManagerView alloc]init]
[self.vw_ownVw addSubview:downLoadMnger.view]
[self.vw_ownVw bringSubviewToFront:downLoadMnger.view]
I am getting this error on second line [self.vw_ownVw addSubview:downLoadMnger.view]
Please help me.
In my experience, what usually causes this error is when memory has been released prematurely. In this case, it is possible that your program is trying to use an array, but because it was not properly retained, the array was deallocated, and an NSString was allocated in the same spot. When your program tries to access the array, it sends the count message to where it thinks the array is, but because a string has been allocated there instead, the string gets the count message and this causes an error because strings don't respond to count.
The code you posted is not the cause of the problem, it is only the point at which this bug is manifesting. In order to find the cause, you need to review your memory management. Try running "Build & Analyze", the static analyser is very good at picking up obvious mistakes in memory management. Review parts of your code that deal with arrays, but keep in mind that the array in question could also be managed by another object outside of your code (such as a view or view controller) that you have released too early, etc.

Resources