I have a problem, where deinit is not called in main code of a command line tool. Here is an example:
import Foundation
class CmyClass {
private var foo : String
init(_ s : String) {
foo = s
print("x: init \(foo)")
}
deinit {
print("x: deinit \(foo)")
}
}
do {
let mc = CmyClass("called in do scope")
}
let mc1 = CmyClass("called in main")
exit(0)
This gives the output
x: init called in do scope
x: deinit called in do scope
x: init called in main
Program ended with exit code: 0
So the deinit is not called if there is no additional scope.
Is it a bug or a feature?
So if a class wraps around external stuff, and needs extraordinary cleanup, the docs for that class has to specify that, that class needs to be inside a scope?
There is no way to absolutely guarantee this. Regardless of what the language does, your process can be killed by the OS at any time, and this is standard policy on many platforms Swift targets—iOS will kill processes when their app is idle (and macOS too if you opt into sudden app termination, which is strongly recommended), and Linux will summarily kill processes when it runs out of memory. If you have cleanup needs that aren't covered by process teardown, you have to be ready to deal with that cleanup potentially not happening.