Без всякой преамбулы я хочу показать вам проблему, с которой я столкнулся в своей программе, я закомментировал шаги и свои мысли для этих шагов. (Я не включил @interface
деталь для краткости, у нее тот же метод с той же сигнатурой, что и у @implementation
)
@implementation Dummy
- (int)testing:(NSError *__strong *)error
{
*error = [[NSError alloc] initWithDomain:@"hello" code:42 userInfo:nil];
// 3. retain count = 1
// 4. because of ARC 'error' object was released for this time
// (assembly output is my proof) object is deallocated
// retain count = 0
return 0;
}
@end
int main()
{
NSError *e = nil; // 1. retain count = 0 (obviously)
Dummy *dummy = [[Dummy alloc] init];
[dummy testing:&e]; // 2. passing reference to an error object
// 'e' for this time has to be just a trash, or nil maybe,
// but next log gives me correct output:
NSLog(@"%@ %li", [e domain], [e code]); // 'hello 42'
return 0;
}
Как существует объект ошибки после его смерти? Я понимаю, что использование NSError *__autoreleasing *
будет правильным путем, и в этом случае ситуация будет тривиальной, но как рассуждения компилятора для этого кода, где моя ошибка в суждениях?
Это немного искусственный вопрос, но я не могу выбросить эту ситуацию из головы, я думаю, что что-то теряю.
Вот часть разборки для -[Dummy testing:]
callq 0x100000e8c <dyld_stub_objc_msgSend>
mov -0x18(%rbp),%rcx
mov (%rcx),%rdx
mov %rax,(%rcx)
mov %rdx,%rdi
callq 0x100000e92 <dyld_stub_objc_release>
mov -0x24(%rbp),%eax
add $0x40,%rsp
pop %rbp
retq
Если я правильно понял, в этом методе есть только один объект, и он явно освобожден, а не выпущен автоматически или что-то еще.