Exemplo de código: Por que ainda posso acessar este objeto NSString depois de lançá-lo?

Eu estava apenas escrevendo algum código exploratório para solidificar minha compreensão do Objective-C e me deparei com este exemplo que não consigo entender. Eu defino esse método e executo o código:

- (NSString *)stringMethod
{
    NSString *stringPointer = [[NSString alloc] initWithFormat:@"string inside stringPointer"];
    [stringPointer release];
    [stringPointer release];
    NSLog(@"retain count of stringPointer is %i", [stringPointer retainCount]);
    return stringPointer;
}

Depois de executar o código e chamar esse método, percebo algumas coisas:

Normalmente, se eu tentar acessar algo que é supostamente desalocado após atingir zero reter count, recebo um erro EXC_BAD_ACCESS. Aqui, eu recebo um erro malloc "double free" em vez disso. Por que é que?

Não importa quantas linhas de "[lançamento do stringPointer]" eu adiciono ao código, o NSLog reporta uma contagem de retenções de 1. Quando eu adiciono mais lançamentos, eu apenas recebo mais erros "double free". Por que as declarações de versão não estão funcionando conforme o esperado?

Embora eu tenha liberado o stringPointer e recebi um monte de erros "double free", o valor de retorno ainda funciona como se nada tivesse acontecido (tenho outro NSLog no código principal que reporta o valor de retorno). O programa continua a funcionar normalmente. Mais uma vez, alguém pode explicar por que isso acontece?

Esses exemplos são bastante triviais, mas estou tentando entender o que está acontecendo. Obrigado!

questionAnswers(3)

yourAnswerToTheQuestion