Swift: How to check if an object is being released - swift

I'm developing a small weak datastructures framework.
A collection of weakely wrapped object has a remove() method.
Inside the method i will delete an object if present and eventually purge the wrappers containing nil references.
The problem raise in the case the weakCollection.remove(object) is called inside a object.deinit() (may happen indirectly).
In this case (since i need to make a copy for comparison reasons) i will have a SIGABORT due to trying to reference an object that is being deallocated and this is forbidden in swift.
Cannot form weak reference to instance (0x608000199710) of class
XXX. It is possible that this object was
over-released, or is in the process of deallocation.
Normally i'd just document it, throw an error or a warning and skip. But i'd like to be safe about this and only remove an object when is not in "releasing" state.
One way would be reading the referenceCount, but in swift is not a good idea. Most other reflection/meta techniques i can think of are too expensive.
Plus: Another thing i'd really appreciate to know is if there is any notification/kno/observer i can connect to in order to be notified when object is being released.

Related

Is it reliable to use an unowned(unsafe) reference while the object in question is deinitializing?

Update
To clarify, the access of the object during its deinitialization is not being done in its deinit method explicitly. The object in question has listers that get added to it (closures) and these closures are all executed within the deinit method. It is within these closures that accesses of the object is being performed with unowned references. And it is the replacement of those unowned references with unowned(unsafe) references that results in EXC_BAD_ACCESS' from no longer occuring.
It is these unowned(unsafe) references that I'm referring to when asking if they're safe to use if always executed during the object in question's deinit.
Original
I wrote a lot of code predicated on being able to clean up unowned references in the deinitializers of their unowned object. Lo and behold, that is not a feature of unowned references. But apparently it is of unowned(unsafe) references, at least that is the way it appears to be working right now — what once caused a crash accessing an unowned reference during its object's deinitialization, now is no longer crashing and is working as expected.
If guaranteed that all unowned references will not be accessed after deinitialization of their object, would it be safe to use it?
For more details, the aforementioned cleaning up entails removing the object from a set where the hashability is based off its contents' object identities. So if it's a plain unowned reference, when the set attempts to access its hash, it will crash if that procedure is being performed while the object is already deinitializing.
The reason the objects aren't removed from the set before they are deinitialized is because this code is a component of library that enables the addition of nodes to a directed acyclic graph. As a feature, I decided that I would not require consumers of the library to have to remove the nodes when they're done with them, they can simply add them to the graph, then when they're done, release their object (the node) as they would anyways, and because the library adds listeners onto the nodes to remove them from the graph in their deinitializers, it was anticipated that it wouldn't be a problem — that the graph would be able to be cleaned up transparently. Obviously it's a little more complicated now that it's apparent that unowned(safe) references can't be accessed while the object they're referencing is deinitializing.
If unowned(unsafe) works in the way it appears to, it would be a solution to this problem.
The only difference between unowned(safe) and unowend(unsafe) is that the save variant is implemented using proxy objects and it will reliably crash your app when you access it illegally.
The unsafe variant on the other hand is just a plain C-Style pointer which will sometimes "just work" (if by coincidence the memory has not been reused anyway) and sometimes will strangely crash or just report unpredicable results.
unowned is the same as unowned(safe)
Nevertheless, during deinit you may access all the propertys of your object, see The Documentation
And also:
I am not sure exactly what you have implemented but it looks like you are trying to duplicate the mechanism with tables Swift uses internally for keeping track of deallocations of weak references.
If guaranteed that all unowned references will not be accessed after
deinitialization of their object, would it be safe to use it?
Yes it would be safe. If you have this guarantee I think it would also be simpler to turn all your variables to implicitly unwrapped weak variables.
So if it's a plain unowned reference, when the set attempts to access
its hash, it will crash if that procedure is being performed while the
object is already deinitializing.
Obviously it's a little more complicated now that it's apparent that
unowned(safe) references can't be accessed while the object they're
referencing is deinitializing.
I do not think this is the reason for the crash, the memory is freed after deinitialization, during deinitialization you still have access to the instance to perform any manual cleanup you need, I would suggest to replace the complicated solution that keeps track of deallocated references, and simply rely on Swift to set to nil objects that are deallocated using weak references. If you do not want to refactor you code to handle optionals when make them explicitly unwrapped.
However if during deinitialization you access the object from an other reference(outside deinit) it will fail, this is to ensure consistency. See here that access an instance that is deinitialized will cause an app to crash.

Is reset member function for weak pointers atomic?

If one creates a shared pointer to an object using std::make_shared, and use a weak pointer to it as an observer. When the reference count of the shared pointer hits zero, the object is not deallocated because the weak pointer keeps it alive. (If I am not mistaken here.) Suppose that after a call of member function lock() on that weak pointer, and it turns out that it has expired. Now the programmer wants to call reset() to trigger destruction of the object, because the object is quite large.
The question is: is reset an atomic operation? If the answer is NO, my next question is that why the standard doesn't requires it being atomic.
The object is only deallocated after each weak_ptr that references the object is reset.
You don't modify single weak_ptr from multiple threads, so reset of a single weak_ptr don't need to be atomic.
C++20 introduces a helper class std::atomic, that guarantees, quote
The partial template specialization of std::atomic for std::weak_ptr allows users to manipulate weak_ptr objects atomically.
If multiple threads of execution access the same std::weak_ptr object
without synchronization and any of those accesses uses a non-const
member function of weak_ptr then a data race will occur unless all
such access is performed through an instance of
std::atomic>.
If one is not using C++20, check this SO answer by Chris Jester-Young for workaround.

For what variables should you use weak var in Swift? How do I figure out the leaks?

I am building an app in Swift. I am creating my views in an entirely a programmatic way. In some instances, I have a ViewController that instantiates custom views. In addition, I may have variables like "var User" which gets populated after an Alamofire network call and is used in various UI elements throughout the view controller. Besides declaring delegates as weak var, are there any other rules that apply?
Also, is there a way for me to figure out whether I have a strong reference that should be a weak one? What should I be looking for?
The basic concept behind reference counting in Swift is one of ownership. Objects should hold strong references to any other objects that they "own", in the sense that they're responsible for the lifecycle of the other object, either alone or in conjunction with other objects.
A lot of object reference graphs in a typical application are hierarchical - one object owns a bunch of other objects, which each have their own children, etc. For example, a ViewController owns its window, the window owns its views, each view owns its subviews, and each subview owns the images, strings, or other content it displays. These are all strong references.
Weak references will typically be used for references that don't imply ownership. The delegate example is a good one - in most cases, a view does not own the delegate. The delegate object has a lifecycle independent of the view. In many cases, the delegate will be the same object that created/owns the view in the first place, for example a ViewController.
You do not want a strong reference that goes from a "child" to its "parent". That creates a circular reference, and both the child and the parent will hang around in memory until the application exits.
In addition to delegates and other "backwards-pointing" references, you will also see weak references used in caches, where you want to quickly return an object if it's requested a second time, but the cache shouldn't keep the object in memory if nobody's currently using it.
To properly answer your question, we would need considerably more detail, (please ...) added to your original question.
I would frankly caution you that "there are no rules" with regards to any issue as fundamentally "touchy" as weak references. Be especially careful not to "follow rules," imagining that thereby you will "be 'safe,'" when other aspects of your application's design do not clearly call for their use.
A "weak" reference is defined as a reference from one thing to another which, you assert, "is not sufficient to cause the referenced object to not be garbage-collected." If the memory-manager does decide to "reap" the object, it is supposed to set your "weak" references to NULL. It can do this at any time will do this at the most-inconvenient time.
One possibility worth contemplating in your application design is to use properties, backed by "getter" routines, instead of actual variables. Or, instead of storing a (weak ...) reference to something, put it into some sort of a "collection" and store its id. Yes, various forms of "getter routines" will be executed each-and-every time, but in the long run that might be more reliable than relying too-much on the memory manager. If you know that "all of the code, wherever situated," will have to pass through "this 'getter' routine," you can concentrate your bug-avoidance efforts at that one deliberate pinch-point.

Using weak reference to check if object is deallocated, in Objective-C

I'm using ARC.
Sometimes I wrote the following code to assert a object should be deallocated:
__weak weakVariableOrProperty = someObject;
....
someObject = nil;
// or someObject = anotherObject;
....
if (weakVariableOrProperty) {
#throw [NSException exceptionWithName:NSInternalInconsistencyException reason:#"Object not deallocated" userInfo:nil];
}
For example, I use this code to check if a view controller is deallocated before creating a new view controller.
I believe that weak variable or weak property is set to nil immediately after last strong variable or property was set to nil or another object.
And this code is working as I expected until now.
Using weak variable or property to check if object is deallocated is a technique commonly used?
Is it possible that this code will cause problem in the future?
I believe that weak variable or weak property is set to nil immediately after last strong variable or property was set to nil or another object.
This is not exactly true, because an object could be autoreleased. In this case, the last strong reference may be gone, but the reference count of the instance would remain positive. In cases like that, the __weak reference would not be nil-ed out until the autorelease process takes place.
Is using weak variable or property to check if object is deallocated a technique commonly used?
I seriously doubt that this technique has gained much popularity, because ARC is a relatively new thing to Objective C. However, the technique appears valid.
Is it possible that this code will cause problem in the future?
This is very hard to guess, because the ARC Specification does not make any specific guarantees about the timing of nil-ing out the references, and because the spec allows compilers to optimize sequences of retain and release messages that they send to ARC objects.
Your explanation code will be prone to a race condition.
The object in weakVariableOrProperty could be released (since it's only referenced by a weak reference) after the if condition has been evaluated. To avoid this, introduce an ordinary variable, set it to weakVariableOrProperty and check it for nil instead.
That said, as #dasblinkenlight says, betting on exactly when an object will be gone is tough. In a reference-counted system you don't know what else is holding onto it. It may go away just after you've checked. You should be able to constrain your environment enough that you know the system's not squirreling things away, but both autorelease and weak references complicate things.
The best way to solve this is simply to have well-defined object lifetimes: view controllers that don't live forever, that you explicitly tell to go away and so on.
So I've tried using this technique to ensure that objects are always deallocated on a background thread. The [dealloc] for some of my classes was moderately heavy weight and could take a long time (10s of ms) which would freeze the main thread ever so slightly.
I decided to add all of these heavy objects to an array before they'd be released on the main thread, and then go through that array later on a backgroundd thread to remove them from the array. The thought was that the array would keep the retainCount alive until it could be removed from the array on the background thread, and then i could guarantee the cost of the [dealloc] wouldn't happen on the main thread.
To do this, i had the code below:
while([objectsToDealloc count] && /* other conditions to prevent infinite loop */){
__weak id ref = [objectsToDealloc lastObject];
[objectsToDealloc removeLastObject];
#synchronized(ref){
// synchronising on ref will retain it if possible.
// so if its still around,that means we didn't dealloc it
// like we were asked to.
// so insert it back into our array. once the object is deallocd
// it won't be able to be synchronized, because the weak ref will
// be nil
if(ref){
[objectsToDealloc insertObject:ref atIndex:0];
}
}
}
The idea was that if the array didn't contain the last reference (or if there were pending autoreleases on the object, etc), then the weak ref wouldn't nil out. I'd then #synchronize on the object - the synchronized block will retain + release whatever object is being synchronized - which would ensure the ref would stay alive during that block. if it was nil, then it'd been dealloced. if it wasn't nil, then i should add it back to the array and check back again later.
After testing with this code over the past few weeks, I cannot recommend this strategy to check for deallocated objects. I haven't tracked down exactly why yet, but very rarely the object will dealloc but the ref won't be nil yet, so i'll be adding an invalid object back into the array.
i've only caught this in the debugger one time, though i have crash logs of it happening a few times. You can see below that "nil" ends up in my array, even though the code above should protect against it.
Again, I suggest not using this technique for detecting when/if objects deallocate, and instead focus efforts on clarifying your object graph and relationships.

My way of creating events is creating a cycle reference where nothings gets released

I have a bunch of objects and I try and simulate events with them.
id completedSelectorTarget;
SEL nextTripSelector;
Then I call perform selector on the selector target.
Well I created a double reference where the listener of the event completedSelectorTarget retains my object and completedSelectorTarget is retained by the object as well.
How do I avoid this? Is there a better way to do events? I thought to remove the retain on completedSelectorTarget, but then what will happen when I call perform selector? The whole thing will crash wont it? Is there a way to check if completedSelectorTarget has been released before I call perform selector? Or perhaps I'm just doing this wrong?
Yes you are correct, you should avoid circular retains.
The way to do this is to decide on an ownership model for these objects. This means deciding which object should have the final say over the life and death of these objects, and a good way to choose this is to pick the object that creates these objects as the owner and main retainer of them. It's not the only way it can be done, but that should be a good start in the right direction. All other relationships should be weak and use assign for the property. In this way you can be sure that when the owner of the objects decides that they should go away, that they will. The owner could also cause these weak links to be cleaned perhaps by calling a method that separates the weak connection by setting the target properties to nil. This is done in case any other object is hanging onto either of the objects and causing the selectors to fire on the targets that have been deallocated.
So you can remove the retain from the completedSelectorTarget properties and make weak connections between the objects.
#property (assign) __weak id completedSelectorTarget;
Once that is done, decide which object is the owner of these objects and make it retain them, either directly using #propery (retain) ..., or perhaps by storing them in a container such as an array or dictionary. When this retain, or container, is released, your object(s) should deallocate or at the very least wind up on an autorelease pool. And you now have a single owner that you can go to to make sure your objects get deallocated.
For now I'm using NSNotification Center. I notice that it crashes as well if you don't remove the observer when it is released. Still it should save me time from writing my own code.