Quando usar -retainCount?

110

Gostaria de saber em que situação você usou -retainCountaté agora e, eventualmente, os problemas que podem ocorrer ao usá-lo.

Obrigado.

Moszi
fonte
5
você nunca deve usar o -retainCount.
holex
3
(Exceto quando deveria. É muito útil ocasionalmente ajudar a entender o que está acontecendo, contanto que você perceba que isso pode ser seriamente enganoso às vezes. E, claro, não é permitido se estiver usando ARC.)
Hot Licks

Respostas:

243

Você nunca deve usar -retainCount, porque nunca diz nada de útil. A implementação dos frameworks Foundation e AppKit / UIKit é opaca; você não sabe o que está sendo retido, por que está sendo retido, quem está retendo, quando foi retido e assim por diante.

Por exemplo:

  • Você pensaria que [NSNumber numberWithInt:1]teria um retainCountigual a 1. Não tem. São 2.
  • Você pensaria que @"Foo"teria um retainCountigual a 1. Não tem. É 1152921504606846975.
  • Você pensaria que [NSString stringWithString:@"Foo"]teria um retainCountigual a 1. Não tem. Novamente, é 1152921504606846975.

Basicamente, uma vez que qualquer coisa pode reter um objeto (e, portanto, alterá-lo retainCount) e como você não tem a fonte para a maior parte do código que executa um aplicativo, o de um objeto não retainCounttem sentido.

Se você está tentando rastrear porque um objeto não está sendo desalocado, use a ferramenta Vazamentos em Instrumentos. Se você está tentando rastrear porque um objeto foi desalocado tão cedo, use a ferramenta Zumbis em Instrumentos.

Mas não use -retainCount. É um método verdadeiramente inútil.

editar

Todos vão para http://bugreport.apple.com e solicitem que -retainCountseja descontinuado. Quanto mais pessoas pedirem, melhor.

editar # 2

Como uma atualização, [NSNumber numberWithInt:1]agora tem um número retainCountde 9223372036854775807. Se seu código esperava que fosse 2, ele agora está corrompido.

Dave DeLong
fonte
4
Obrigado @ Dave-Delong por seus exemplos.
Moszi
1
HoldCount é atualmente útil para singletons. (Agora a questão é quão úteis são singletons ...) - (NSUInteger)retainCount{return NSUIntegerMax;}.
Joe
8
@Joe você pode fazer um singleton sem substituí-lo retainCount.
Dave DeLong
5
@Joe estou ciente disso; Google "singleton objetivo-c" para toda a discussão sobre por que esse exemplo não é muito bom.
Dave DeLong
2
Uma coisa que eu uso - @ DaveDeLong, você pode achar isso errado também, mas eu acho que não - é sobrescrever os desalocadores e os inits e colocar NSLogs neles (mesmo com ARC). Isso me dá uma ótima ideia se os objetos estão sendo desalocados ou não, que é a verdadeira questão que geralmente estamos tentando responder.
Dan Rosenstark
50

NUNCA!

Seriamente. Só não faça isso.

Basta seguir as diretrizes de gerenciamento de memória e apenas liberar o que você alloc, newoucopy (ou qualquer coisa que você chamado retainem cima originalmente).

@bbum disse isso melhor aqui no SO , e com ainda mais detalhes em seu blog .

Abizern
fonte
8
Porque você vai pensar que está contando a memória, mas estará fazendo errado.
Abizern
@Abizern - e quanto à situação do singleton em uma das outras respostas?
Moszi
3
Para adicionar a isso, qualquer informação que você possa obter -retainCountpode ser obtida (com muito mais detalhes) de Instrumentos e suas ferramentas.
Dave DeLong
3
Para adicionar ao que Dave disse; a contagem de retenção absoluta de um objeto é um detalhe de implementação. Tanto um detalhe da parte interna do objeto e / ou um detalhe de qualquer outro objeto pelo qual o objeto pode ter passado. Chamando retain, retain, retain, autorelease, disparo automático, autoreleasepoderia ser um resultado perfeitamente válida de passar um objeto por meio da API UIKit, por exemplo.
bbum de
2
@ d11wtq Se retêmConta alguma vez == 0, a singularidade foi alcançada!
bbum de
14

Objetos liberados automaticamente são um caso em que a verificação de -retainCount não é informativa e é potencialmente enganosa. A contagem de retenção nada diz sobre quantas vezes -autorelease foi chamado em um objeto e, portanto, quantas vezes ele será liberado quando o pool de autorelease atual for drenado.

Jonah
fonte
1
Obrigado - este é um bom ponto. Esta é a primeira resposta que na verdade tem um motivo descrito para não usar reterCount, além do genérico "não".
Moszi
1
@Moszi: Sua pergunta era "Quando usar a retençãoCount?" - se você não quis fazer essa pergunta, você deveria ter perguntado outra coisa.
Chuck
@chuck - na verdade eu estava interessado em "quando usar", no entanto, parece que toda resposta será "nunca" ... Mas - acho que você está certo. Deixarei a pergunta em aberto por alguns dias e, se não houver resposta, então nunca, aceitarei "nunca" como resposta.
Moszi
10

Eu não encontrar retainCounts muito útil quando verificada com 'instrumentos'.

Usando a ferramenta 'alocações', certifique-se de que 'Registrar contagens de referência' esteja ativado e você possa acessar qualquer objeto e ver seu histórico de reterContagem.

Ao emparelhar alocações e liberações, você pode ter uma boa imagem do que está acontecendo e, muitas vezes, resolver os casos difíceis em que algo não está sendo liberado.

Isso nunca me decepcionou - incluindo encontrar bugs nas primeiras versões beta do iOS.

Egil
fonte
5

Dê uma olhada na documentação da Apple sobre NSObject, ela cobre praticamente sua pergunta: NSObject repeatCount

Em suma, retémCount provavelmente é inútil para você, a menos que tenha implementado seu próprio sistema de contagem de referência (e quase posso garantir que não o terá).

Nas próprias palavras da Apple, retémCount "normalmente não tem valor na depuração de problemas de gerenciamento de memória".

lxt
fonte
Antes de mais nada obrigado pela sua resposta. Normalmente a reação das pessoas a esta pergunta é "NUNCA". (Veja as respostas). Na verdade, "nenhum valor na depuração" não significa "NUNCA". Portanto, minha pergunta é - por que a forte sensação de não usá-lo (por exemplo, na implementação de singleton - uma das respostas novamente)?
Moszi
Suponho que você precise fornecer mais informações sobre a finalidade de seu uso. Um uso aceitável seria, conforme sugerido pela Apple, substituir a retençãoCount para implementar seu próprio sistema de contagem de referência. Mas, na prática, você nunca veria isso (nunca vi, de qualquer maneira). A forte reação geralmente vem do fato da própria Apple ter defendido (em seus grupos de e-mail, nos documentos, nos fóruns de desenvolvimento, etc) para deixar o retentCount sozinho.
lxt
1
@Moszi: A depuração é a única situação em que a maioria das pessoas poderia conceber que ela tivesse valor, então, se não for confiável lá, nunca será útil. Em que outros usos você está pensando?
Chuck
4

É claro que você nunca deve usar o método retentCount em seu código, já que o significado de seu valor depende de quantas autoreleases foram aplicadas ao objeto e isso é algo que você não pode prever. No entanto, é muito útil para depuração - especialmente quando você está caçando vazamentos de memória no código que chama métodos de objetos Appkit fora do loop de evento principal - e não deve ser descontinuado.

Em seu esforço para demonstrar seu ponto de vista, você exagerou seriamente a natureza inescrutável do valor. É verdade que nem sempre é uma contagem de referência. Existem alguns valores especiais que são usados ​​para sinalizadores, por exemplo, para indicar que um objeto nunca deve ser desalocado. Um número como 1152921504606846975 parece muito misterioso até que você o escreva em hexadecimal e obtenha 0xfffffffffffffff. E 9223372036854775807 é 0x7fffffffffffffff em hexadecimal. E realmente não é tão surpreendente que alguém opte por usar valores como esses como sinalizadores, visto que levaria quase 3.000 anos para obter um retémContagem tão alto quanto o maior número, supondo que você incrementou retentãoContagem 100.000.000 vezes por segundo.

Marc Culler
fonte
3

Que problemas você pode obter ao usá-lo? Tudo o que faz é retornar a contagem de retenção do objeto. Nunca liguei para isso e não consigo pensar em nenhum motivo para fazer isso. Eu o substituí em singletons para garantir que eles não sejam desalocados.

ughoavgfhw
fonte
2
Não há razão para substituí-lo no caso único. Não há caminhos de código na Foundation / CoreFoundation que sejam usados retainCountpara gerenciamento de memória.
bbum de
O release não o usa para decidir se deve chamar o dealloc?
ughoavgfhw
2
Não; a implementação interna de reter / liberar / autorelease tem raízes profundas no CoreFoundation e realmente não é o que você poderia esperar. Vá pegar o código-fonte CoreFoundation (está disponível) e dê uma olhada.
bbum de
3

Você não deve se preocupar com vazamento de memória até que seu aplicativo esteja instalado, funcionando e fazendo algo útil.

Assim que estiver, inicie o Instruments e use o aplicativo para ver se vazamentos de memória realmente acontecem. Na maioria dos casos, você mesmo criou um objeto (portanto, você o possui) e se esqueceu de liberá-lo após terminar.

Não tente otimizar seu código enquanto o escreve, seus palpites sobre o que pode vazar memória ou demorar muito estão frequentemente errados quando você realmente usa o aplicativo normalmente.

Tente escrever o código correto, por exemplo, se você criar um objeto usando aloc e tal, certifique-se de liberá-lo corretamente.

ExitToShell
fonte
0

Você nunca deve usá-lo em seu código, mas pode definitivamente ajudar na depuração

Iosdevnyc
fonte
0

Nunca use o -retainCount em seu código. No entanto, se você usar, nunca verá que ele retorna zero. Pense no porquê. :-)

Hrchen
fonte
0

Os exemplos usados ​​na postagem de Dave são NSNumber e NSStrings ... então, se você usar algumas outras classes, como UIViews, tenho certeza de que obterá a resposta correta (a contagem de retenção depende da implementação e é previsível).

Peng
fonte