问题
I have a set of classes forming a decorator pattern so that I can do some layered caching. I have an abstract class which provides the core processing of images and contains a number of overridable functions where implementations can add their individual processing.
When saving an image I have the following code:
func cacheImage(_ key:String, image:UIImage?) {
if let image = image {
saveImage(key, image:image)
} else {
deleteImage(key)
}
backingCache?.cacheImage(key, image:image)
}
func saveImage(_ key:String, image:UIImage) {}
func deleteImage(_ key:String) {}
This is where it gets weird. When compiled for Release, this code will generate an EXC_BAD_ACCESS. Tracing it with Zombies on shows messages being sent to UIImage instances after they have been deallocated.
If I attempt to get more information by compiling with the Debug configuration, the EXC_BAD_ACCESS stop occurring. Making it very difficult to debug.
I've found that if I add a print(...)
statements like this:
func deleteImage(_ key:String) {
print("Abstract delete image")
}
the EXC_BAD_ACCESS goes away.
My current theory is that without the print(...)
, Swift is aggressively de-allocing the image instances. I also remember reading something about Debug delaying ARC's garbage collection which would explain why the EXC_BAD_ACCESS doesn't occur in debug.
I've also now found that changing the method signature to:
open func deleteImage(_ key:String) {}
Also removes the EXC_BAD_ACCESS.
Can anyone give a more detailed explanation of why the EXC_BAD_ACCESS zombies are occurring? I can't see why in the first place.
来源:https://stackoverflow.com/questions/41528974/perhaps-the-weirdest-exc-bad-access-ive-seen-swift-generate