Pelo que entendi, qualquer coisa criada com uma alocação , nova ou cópia precisa ser liberada manualmente. Por exemplo:
int main(void) {
NSString *string;
string = [[NSString alloc] init];
/* use the string */
[string release];
}
Minha pergunta, porém, é que isso não seria tão válido ?:
int main(void) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
[pool drain];
}
objective-c
memory-management
nsautoreleasepool
foundationkit
James Sumners
fonte
fonte
an object
deveria seran object that is a subclass of NSObject or NSProxy and doesn't override -autorelease
.NSAutoreleasePool: drenagem vs. liberação
Visto que a função de
drain
erelease
parece estar causando confusão, pode valer a pena esclarecer aqui (embora isso seja abordado na documentação ...).Estritamente falando, da perspectiva do quadro geral não
drain
é equivalente a :release
Em um ambiente de contagem de referência,
drain
executa as mesmas operações querelease
, portanto, os dois são equivalentes nesse sentido. Para enfatizar, isso significa que você não vaza uma piscina se usar emdrain
vez derelease
.Em um ambiente com coleta de lixo,
release
é um ambiente autônomo. Portanto, não tem efeito.drain
, por outro lado, contém uma dica para o coletor de que ele deve "coletar se necessário". Portanto, em um ambiente com coleta de lixo, o usodrain
ajuda o sistema a equilibrar as varreduras de coleta.fonte
NSAutoreleasePool
. Isso ocorre porque os pools funcionam como uma pilha. Instanciar um pool empurra aquele pool para o topo da pilha do pool de liberação automática de threads.-release
faz com que aquele pool saia da pilha E quaisquer pools que foram colocados em cima dele, mas por alguma razão não foram retirados.Como já apontado, seu segundo trecho de código está correto.
Eu gostaria de sugerir uma maneira mais sucinta de usar o pool de autorelease que funciona em todos os ambientes (contagem de ref, GC, ARC) e também evita a confusão de drenagem / liberação:
No exemplo acima, observe o bloco @autoreleasepool . Isso está documentado aqui .
fonte
@autoreleasepool
bloco com ARC.Não, você está errado. A documentação afirma claramente que sob não-GC, -drain é equivalente a -release, o que significa que o NSAutoreleasePool não vazará.
fonte
NSAutoreleasePool
: developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…O que li da Apple: "No final do bloco do pool de autorelease, os objetos que receberam uma mensagem de autorelease dentro do bloco recebem uma mensagem de release - um objeto recebe uma mensagem de release para cada vez que foi enviada uma mensagem de autorelease dentro do bloco. "
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
fonte
enviar liberação automática em vez de liberação para um objeto estende a vida útil desse objeto pelo menos até que o próprio pool seja drenado (pode ser mais longo se o objeto for retido posteriormente). Um objeto pode ser colocado no mesmo pool várias vezes e, nesse caso, ele recebe uma mensagem de liberação para cada vez que foi colocado no pool.
fonte
Sim e não. Você acabaria liberando a memória da string, mas "vazando" o objeto NSAutoreleasePool na memória usando drenagem em vez de liberação se executasse isso em um ambiente de coleta de lixo (não gerenciado por memória). Esse "vazamento" simplesmente torna a instância de NSAutoreleasePool "inacessível" como qualquer outro objeto sem ponteiros fortes em GC, e o objeto seria limpo na próxima vez que GC fosse executado, o que poderia muito bem ser diretamente após a chamada para
-drain
:Caso contrário, é semelhante ao
-release
comportamento em não-GC, sim. Como outros afirmaram,-release
é um ambiente autônomo no GC, então a única maneira de garantir que o pool funcione corretamente no GC é através-drain
, e-drain
no não-GC funciona exatamente como-release
no não-GC, e pode-se dizer que comunica sua funcionalidade mais claramente conforme bem.Devo ressaltar que sua instrução "qualquer coisa chamada com new, aloc ou init" não deve incluir "init" (mas deve incluir "copiar"), porque "init" não aloca memória, apenas configura o objeto (construtor moda). Se você recebeu um objeto alocado e sua função apenas chamada init como tal, você não o liberaria:
Isso não consome mais memória do que você já começou (assumindo que o init não instancia objetos, mas você não é responsável por eles).
fonte
-[NSAutoreleasePool release]
em um ambiente com coleta de lixo é autônomo.-[NSAutoreleasePool drain]
funciona em ambientes com contagem de referência e com coleta de lixo.