ARC doesn't apply to struct and enum, how are they deallocated in Swift - swift

Since ARC doesn't apply to struct and enum, then how are they deallocated from the memory? I have to get stuck when it asked in the interviews and try to find the correct answer but can't find much info on it googling. I know swift is smart at handling value types. But how?

The memory management of objects (instances of classes) is relatively difficult, because objects can outlive a function call, the life of other objects, or even the life of the threads that allocated them. They're independent entities on the heap, that need book keeping to make sure they're freed once they're not needed (once they're no longer referenced from any other threads/objects, they're unreachable, thus can't possible be needed, so are safe to delete).
On the other hand, structs and enums just have their instances stored inline:
If they're declared as a global variable, they're stored in the program text.
If they're declared as a local variable, they're allocated on the stack (or in registers, but never mind that).
If they're allocated as a property of another object, they're just
stored directly inline within that object.
They're only ever deleted
by virtue of their containing context being deallocated, such as when
a function returns, or when an object is deallocated.

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.

If a function returns an UnsafeMutablePointer is it our responsibility to destroy and dealloc?

For example if I were to write this code:
var t = time_t()
time(&t)
let x = localtime(&t) // returns UnsafeMutablePointer<tm>
println("\(x.memory.tm_hour): \(x.memory.tm_min): \(x.memory.tm_sec)")
...would it also be necessary to also do the following?
x.destroy()
x.dealloc(1)
Or did we not allocate the memory and so therefore don't need to dismiss it?
Update #1:
If we imagine a function that returns an UnsafeMutablePointer:
func point() -> UnsafeMutablePointer<String> {
let a = UnsafeMutablePointer<String>.alloc(1)
a.initialize("Hello, world!")
return a
}
Calling this function would result in a pointer to an object that will never be destroyed unless we do the dirty work ourselves.
The question I'm asking here: Is a pointer received from a localtime() call any different?
The simulator and the playground both enable us to send one dealloc(1) call to the returned pointer, but should we be doing this or is the deallocation going to happen for a returned pointer by some other method at a later point?
At the moment I'm erring towards the assumption that we do need to destroy and dealloc.
Update #1.1:
The last assumption was wrong. I don't need to release, because I didn't create object.
Update #2:
I received some answers to the same query on the Apple dev forums.
In general, the answer to your question is yes. If you receive a pointer to memory which you would be responsible for freeing in C, then you are still responsible for freeing it when calling from swift ... [But] in this particular case you need do nothing. (JQ)
the routine itself maintains static memory for the result and you do not need to free them. (it would probably be a "bad thing" if you did) ... In general, you cannot know if you need to free up something pointed to by an UnsafePointer.... it depends on where that pointer obtains its value. (ST)
UnsafePointer's dealloc() is not compatible with free(). Pair alloc() with dealloc() and malloc and co. with free(). As pointed out previously, the function you're calling should tell you whether it's your response to free the result ... destroy() is only necessary if you have non-trivial content* in the memory referred to by the pointer, such as a strong reference or a Swift struct or enum. In general, if it came from C, you probably don't need to destroy() it. (In fact, you probably shouldn't destroy() it, because it wasn't initialized by Swift.) ... * "non-trivial content" is not an official Swift term. I'm using it by analogy with the C++ notion of "trivially copyable" (though not necessarily "trivial"). (STE)
Final Update:
I've now written a blogpost outlining my findings and assumptions with regard to the release of unsafe pointers taking onboard info from StackOverflow, Apple Dev Forums, Twitter and Apple's old documentation on allocating memory and releasing it, pre-ARC. See here.
From Swift library UnsafeMutablePointer<T>
A pointer to an object of type T. This type provides no automated
memory management, and therefore the user must take care to allocate
and free memory appropriately.
The pointer can be in one of the following states:
memory is not allocated (for example, pointer is null, or memory has
been deallocated previously);
memory is allocated, but value has not been initialized;
memory is allocated and value is initialized.
struct UnsafeMutablePointer<T> : RandomAccessIndexType, Hashable, NilLiteralConvertible { /**/}

Why Use Properties?

So I've been programming on Objective-C for over a year now, and I can't seem to understand the use for properties. I have searched the internet a few times but never really found a good explaniation. I understand how to create them:
#property (something, something) something *variableName;
#syntheize variableName;
But should I make all my instance variables properties. To me, from what I know, it seems like a waste of code. But when I look at code online, sometimes I see like 25 properties in one class. Which I think is a waste. The only time I ever use them is when passing info from a UITableView cell selected to a detail viewController. For that, I use:
#property (copy) NSString *myString;
Can you also explain what: nonatomic, copy, retain, assign, etc. mean.
Thanks
These properties are convenience methods for creating getters and setters.
Atmoic v Nonatomic
Assuming that you are #synthesizing the method implementations, atomic vs. non-atomic changes the generated code. If you are writing your own setter/getters, atomic/nonatomic/retain/assign/copy are merely advisory.
With atomic, the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than atomic.
What atomic does not do is make any guarantees about thread safety. If thread A is calling the getter simultaneously with thread B and C calling the setter with different values, thread A may get any one of the three values returned -- the one prior to any setters being called or either of the values passed into the setters in B and C. Likewise, the object may end up with the value from B or C, no way to tell.
Ensuring data integrity -- one of the primary challenges of multi-threaded programming -- is achieved by other means.
Assign, retain, copy
In a nutshell, assign vs retain vs copy determines how the synthesized accessors interact with the Objective-C memory management scheme:
assign is the default and simply performs a variable assignment
retain specifies the new value should be sent -retain on assignment and the old value sent release
copy specifies the new value should be sent -copy on assignment and the old value sent release.
Remember that retain is done on the created object (it increases the reference count) whereas copy creates a new object. The difference, then, is whether you want to add another retain to the object or create an entirely new object.
Properties are a good technique to expose values. You shouldn't expose all instance variables as that would break good OOP encapsulation.
Here is Apple's documentation on the matter.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
A key point is:
Declared properties address the problems with standard accessor
methods by providing the following features:
The property declaration provides a clear, explicit specification of
how the accessor methods behave.
The compiler can synthesize accessor methods for you, according to
the specification you provide in the declaration. This means you have
less code to write and maintain.
Properties are represented syntactically as identifiers and are
scoped, so the compiler can detect use of undeclared properties.
Properties enable automatic handling of the variables. So when you do a synthesize the compiler will generate your getters and setters allowing one to do class.variableName = value (indicating that the compiler will execute [class variableName:value].
Pretty decent explanation of the properties here: http://cocoacast.com/?q=node/103
If you need getters and setters to expose some instance variables, or you want some automatic retain/release memory management or thread safe accessors, then properties are a less verbose way to automatically create these smart getters and setters. If you don't want to expose something outside an object or thread, and don't want runtime memory management (say, for some malloc'd C struct) then properties might either a waste, or syntactic sugar (which may or may not improve code readability), or put there by a coder who doesn't know the difference.
The properties is a nice feature which gives you getter and setter method automatically by synthesize and give you relief by not setting and getting the value.
A property may be declared as "readonly", and may be provided with storage semantics such as "assign", "copy" or "retain". By default, properties are considered atomic, which results in a lock preventing multiple threads from accessing them at the same time. A property can be declared as "nonatomic", which removes this lock (reference from http://en.wikipedia.org/wiki/Objective-C#Properties).

Memory Leaks in Objective-C / Arrays

I'm looking at someone's code and I know the general rule is if you have alloc/init, you need to release that memory. He uses a lot of NSMutableArrays, alloc/inits them, but does not release them. Can I simply send the autorelease message to the array that gets created if I do not see any other release/autorelease message getting sent to that array? I basically don't want to get his code to crash and stop working either :P.
With NSMutableArrays, when you send the message addObject and the object in that array increases its retain account, if that array gets released, but the object never gets sent a release or removeObject from the array, is that also a memory leak? Thanks.
You need to either -release or -autorelease anything you -retain, +alloc, -copy, +allocWithZone: or -copyWithZone:. (And, if you retain something twice you also need to release it twice.)
When an NSMutableArray (or NSArray, NSSet, or NSDictionary and mutable subclasses) object is dealloc'd (retain count reaches zero), it releases anything it contains. When you add an object to an NSMutableArray, the array retains the object (it does not copy it like some people claim).
I highly recommend the Memory Management Programming Guide to both you and the someone you referred to in the question.
I hope this answer helps you and someone. Good luck. :)
Also, enable the Clang Static Analyser in the build settings. This will tell you at compile time when a leak is going to happen (and much, much more). In fact, it's the first thing I always do when I start a new project. The analyzer never lied to me.
NSArray and NSMutableArray release all of their objects when they are destroyed, so if the array is managed properly with retain and release (or autorelease) the objects within will not be leaked. But if there are arrays that are never released, they will leak, along with everything inside them.
Without seeing the code, it's hard to advocate for just adding autoreleases everywhere, but for arrays that are used only in the context of a single function (and not assigned to ivars or static variables), the answer is yes, they should be autoreleased. Or more idiomatically, create them with methods like +arrayWithCapacity, which returns an object that has already been added to the autorelease pool.
It is general practice to release all the objects you initialize. But in your case, releasing the array should release all objects as well.
But it all depends on how you are using your objects !!!

Raw data types Vs Objects in Objective C

Something I've been wondering for a while. I know that in order to free up memory, objects (Such as NSMutableArray) have to be released, but raw data types (Such as int) don't. My question is, at what point does the space in memory that an int is occupying become free?
For example, a class "myClass" has an iVar "int a"
"a" holds the value some integer value.
When "myClass" is deallocated, does the space in memory that was holding the value for "a" become free straight away?
Thanks in advance.
For class ivars, the memory is freed when the object instance is deallocated - upon the last [release] call. For local int (and other primitive) variables, when the function returns. For global and static variables, when the process quits.
Also, you can allocate int's dynamically with malloc(). Then it's freed when you call free().
"a" is included in the memory allocated in "myClass". In other words, when myClass is deallocated, "a" is gone right along with it.
An Objective C object is similar to a pointer to a malloc'd C structure (containing both declared and a few hidden instance variables). When an object is released, the entire C structure memory block, including all internal ivar storage, is free'd (as well as any other dealloc housekeeping required).