Explicação de armazenamento forte e fraco no iOS5

114

Eu sou novo no desenvolvimento de iOS5 e uso o objetivo-c. Tenho dificuldade em entender a diferença entre armazenamento forte e fraco . Eu li a documentação e outras perguntas do SO, mas todas parecem idênticas para mim, sem nenhuma percepção adicional.

Eu li a documentação: Transitioning para ARC - faz referência aos termos de retenção, atribuição e liberação do iOS4; o que me confunde. Em seguida, analiso o Open U CS193p, onde diferencia forte e fraco:

Forte : "mantenha isso na pilha até que eu não aponte mais para ele"
Fraco : "mantenha enquanto alguém apontar fortemente"

As duas definições não são idênticas = se o ponteiro não estiver mais apontando para um objeto, então libere a memória que contém o objeto? Eu entendo o conceito de ponteiros, heap, alocação ou desalocação de memória - mas qual é a diferença entre forte e fraco?

KMC
fonte
O modelo de gerenciamento de memória ainda é relevante, embora você esteja usando o ARC. Você ainda precisa entender a contagem de referência, mas não precisa fazer isso manualmente. Portanto, o seu último parágrafo é uma exigência irracional.
jrturton

Respostas:

509

A diferença é que um objeto será desalocado assim que não houver indicadores fortes para ele. Mesmo se os ponteiros fracos apontarem para ele, assim que o último ponteiro forte for eliminado, o objeto será desalocado e todos os ponteiros fracos restantes serão zerados.

Talvez seja necessário um exemplo.

Imagine que nosso objeto é um cachorro e que o cachorro quer fugir (ser desalocado).

Dicas fortes são como uma coleira no cão. Contanto que você tenha a guia presa ao cão, o cão não fugirá. Se cinco pessoas prenderem a coleira em um cão (cinco pontas fortes em um objeto), o cão não fugirá até que todas as cinco coleiras sejam retiradas.

Os ponteiros fracos, por outro lado, são como crianças apontando para o cachorro e dizendo "Olhe! Um cachorro!" Enquanto o cachorro ainda estiver na coleira, as crianças pequenas ainda podem ver o cachorro e ainda apontam para ele. Assim que todas as coleiras são retiradas, porém, o cão foge, não importa quantas crianças apontem para ele.

Assim que o último ponteiro forte (leash) não apontar mais para um objeto, o objeto será desalocado e todos os ponteiros fracos serão zerados.

BJ Homer
fonte
2
É baseado em uma analogia que Malcom Crawford, da Apple, deu alguns anos atrás. Não sei onde ele conseguiu.
BJ Homer
Lembro-me de ter lido algo semelhante (pré-arco) em um livro, acho que foi Hillegass, mas então ele poderia ter conseguido de outro lugar ... é um bom livro!
jrturton
14
+1 excelente exemplo. é um derivado do exemplo de Hillegass sobre como as coleiras são retidas / liberadas, mas adoro essa adaptação para forte / fraco.
Dave DeLong
2
@DaveDeLong: Bem, eles são ilegais em 10.6 com ARC. Você não pode usá-los de forma alguma. Então esse é um ponto irrelevante.
BJ Homer
5
Outro bom são os balões de hélio: enquanto pelo menos uma corda for segurada, ela não vai flutuar. As analogias guia / balão também são boas para fazer as pessoas esquecerem que a "propriedade" é gerenciada por meio de retenção / liberação.
Steve Weller
34

As duas definições não são idênticas.

Absolutamente não. A principal diferença nas duas definições que você apontou é "enquanto outra pessoa". É a "outra pessoa" que é importante.

Considere o seguinte:

__strong id strongObject = <some_object>;
__weak id weakObject = strongObject;

Agora temos dois indicadores para <some_object>, um forte e outro fraco. Se colocarmos strongObjecta nilassim:

strongObject = nil;

Então, se você seguir as regras que descreveu, você se perguntará o seguinte:

  1. Forte: "mantenha isso na pilha até que eu não aponte mais para ele"

    strongObjectnão aponta para <some_object>mais nada. Portanto, não precisamos mantê-lo.

  2. Fraco: "mantenha isto enquanto alguém apontar fortemente"

    weakObjectainda aponta para <some_object>. Mas, como ninguém mais aponta para ela, essa regra também significa que não precisamos mantê-la.

O resultado é que <some_object>é desalocado e se o seu tempo de execução oferecer suporte (Lion e iOS 5 ou superior), weakObjectserá automaticamente definido como nil.

Agora, considere o que acontece se definir weakObjecta nilassim:

weakObject = nil;

Então, se você seguir as regras que descreveu, você se perguntará o seguinte:

  1. Forte: "mantenha isso na pilha até que eu não aponte mais para ele"

    strongObjectaponta para <some_object>. Portanto, precisamos mantê-lo.

  2. Fraco: "mantenha isto enquanto alguém apontar fortemente"

    weakObjectnão aponta para <some_object>.

O resultado é que não<some_object> é desalocado, mas será o ponteiro.weakObjectnil

[Observe que tudo o que está assumindo <some_object>não é apontado por outra referência forte em algum outro lugar / algum outro meio de ser "mantido"]

mattjgalloway
fonte
1
Portanto, a principal diferença entre forte e fraco é que a desalocação de objetos apontados com força anulará automaticamente todos os ponteiros fracos relacionados. E para um ponteiro fraco apontar para algo, sempre existe um ponteiro forte. Em caso afirmativo, o objeto do aplicativo principal deve ser fortemente apontado?
KMC
Para um ponteiro fraco apontar para algo válido , sim, deve haver um ponteiro forte. Adicione a isso o fato de que o iOS 5 e o Lion oferecem suporte para anulação automática de referências fracas e você terá o que dizer. O tempo de execução do iOS 4 não suporta isso. O "objeto do aplicativo principal" Presumo que você se refira ao UIApplicationobjeto? Isso será fortemente referenciado pelo funcionamento interno de UIKit- mas você não precisa se preocupar com isso.
mattjgalloway
Acho que você pode usar a palavra como "strongObjectPointer" em vez de "strongObject". Portanto, novas pessoas para a programação terão um significado melhor. Boa pegada no post de @BJ Homer Mr.Matt.Interesting :)
Vijay-Apple-Dev.blogspot.com
2

Forte

  1. Cria propriedade entre propriedade e valor atribuído.
  2. Este é o padrão para a propriedade do objeto no ARC, portanto, não o deixa se preocupar com a contagem de referência e libera a referência automaticamente.
  3. É um substituto para reter. Usamos se e somente se precisarmos usar como reter.

Fraco

  1. Cria não propriedade entre a propriedade e o valor atribuído.
  2. Forte é usado no objeto pai e fraco é usado no objeto filho quando o pai é liberado, então a referência do objeto filho também é definida como nula
  3. Ajuda a prevenir ciclos de retenção.
  4. Ele não protege o objeto referenciado durante a coleta pelo coletor de lixo.
  5. Fraco é essencialmente atribuído, propriedade não retida.
Shashi3456643
fonte
Vale a pena mencionar aqui o que normalmente é o ciclo de retenção. Temos dois objetos: objeto A e objeto B. O objeto A tem uma referência forte ao objeto B e o objeto B tem uma referência forte ao objeto A. Nada mais tem uma referência forte ao objeto A ou B.
boro
2

Outro exemplo: Aluno é um Object, suposto que pode graduar-se ( deallocate) desde que tenha concluído todos os cursos básicos ( strong pointers), independentemente de cursar cursos opcionais ( weak pointers). Em outras palavras: o ponteiro forte é o único fator de desalocação disso Object.

RobotCharlie
fonte
1

Não, eles não são idênticos, mas muito diferentes. Você usa forte apenas se precisar reter o objeto. Você usa fraco em qualquer outro caso, com a vantagem de saber se o objeto foi removido do heap porque ninguém o está retendo.

Gabriel
fonte
1

Sei que estou um pouco atrasado para esta festa, mas acho importante confundir a questão apontando que o significado de "modelos de memória fortes e fracos" depende se você está falando sobre software ou hardware.

Para hardware, fraco ou forte indica se há suporte para consistência sequencial.

[SC significa que] ... o resultado de qualquer execução é o mesmo como se as operações de todos os processadores fossem executadas em alguma ordem sequencial, e as operações de cada processador individual aparecem nesta sequência na ordem especificada por seu programa. - Lamport, 1979

WTF isso tem a ver com memória? Isso implica que as gravações em variáveis ​​por diferentes processadores devem ser vistas na mesma ordem por todos os processadores. Em hardware com um modelo forte, isso é garantido. No hardware com um modelo fraco, não é.

As respostas existentes interpretam a pergunta apenas em termos de modelos de memória de software. Hardware não é irrelevante para a programação. Essa mesma pergunta menciona o iOS, que normalmente é executado em processadores Arm7. Arm7 tem um modelo de memória fraco. Para programadores acostumados a processadores com um modelo forte - que somos todos nós porque x86 e x64 têm um modelo forte - esta é uma armadilha terrível. Usar um bool para sinalizar a saída de outro thread funciona bem em um modelo forte. O mesmo código no Arm não funciona a menos que você marque a bandeira como volátil, e mesmo assim é errático.

Embora seja verdade que o Arm8 + muda isso totalmente com suporte explícito para aquisição / lançamento, o software legado não usa esse suporte. O software legado inclui todos os três sistemas operacionais de telefone e tudo o que é executado neles, bem como compiladores e bibliotecas até que sejam atualizados.

Para um exame mais extenso deste tópico, remeto-o ao inimitável Herb Sutter .

Peter Wone
fonte