Неверно закодированная ленивая инициализация работает хорошо - PullRequest
1 голос
/ 07 июня 2011

Намеренно ли неправильно кодированный ленивый init:

-(X*) prop {
    if (!prop) {
        prop = [[Prop alloc] init];
        return prop;
    }
    // RETURN SHOULD BE HERE 
}

, тем не менее, делает «правильную вещь» из-за сгенерированной последовательности кода ниже?

  • загрузка реквизита вrax для теста
  • возвращающий rax в любом случае

Ответы [ 2 ]

4 голосов
/ 07 июня 2011

Это не преднамеренно, и даже если это работает, вы не должны полагаться на это.Например, рассмотрим следующее:

- (NSString *)someString {
    if (! someString) {
        someString = [[NSString alloc] initWithFormat:@"%d", 5];
        return someString;
    }
}

При компиляции с gcc -O0:

movq    -24(%rbp), %rdx
movq    _OBJC_IVAR_$_SomeClass.someString@GOTPCREL(%rip), %rax
movq    (%rax), %rax
leaq    (%rdx,%rax), %rax
movq    (%rax), %rax
testq   %rax, %rax

и код действительно работает, потому что, как вы заметили, ивар загружается вRAX.

Однако при компиляции с gcc -O3:

    movq    %rdi, %rbx
    addq    _OBJC_IVAR_$_SomeClass.someString(%rip), %rbx
    cmpq    $0, (%rbx)
    je  L5
L4:
    movq    (%rsp), %rbx
    movq    8(%rsp), %r12

К сожалению, нет возвращаемого значения в RAX - ивар был загружен в RBX.Этот код работает при первом вызове (тот, который лениво инициализирует ivar), но вылетает при втором вызове.

2 голосов
/ 07 июня 2011

это намеренно, что ленивый init неправильно закодирован:

Нет.

Вам просто повезло, что использовался стандартный регистр возврата.Никогда не полагайся на это.Фактически, это должно дать вам предупреждение компилятора.

...