Co zrobić, jeśli mam obiekt, powiedzmy NSIndexPath, w którym przed wykonaniem kopii zawsze najpierw go zwalniam?
Czy można mieć liczbę pamięci poniżej 0? Robię to, aby zapobiec wyciekom pamięci.. czy to dobry sposób?
//global ma już wcześniej jakąś wartość tutaj lub nie ma wartości. Chcę zaktualizować
//to z nową wartością (nie obchodzi mnie stary wskaźnik)
[global release]
global = [indexPath copy];
2 odpowiedzi
Nie. Gdy liczba zachowań osiągnie 0, twój obiekt zostanie cofnięty, a jego wskaźnik stanie się nieważny, więc ponowne użycie go spowoduje nieprzewidywalne wyniki (mianowicie awarię).
Należy zapoznać się z Przewodnik zarządzania pamięcią.
Oto podstawowa zasada:
- Zwalniasz lub automatycznie zwalniasz tylko obiekty, których jesteś właścicielem. Przejmujesz własność obiektu, jeśli utworzysz go za pomocą metody, której nazwa zaczyna się od „alloc”, „new”, „copy” lub „mutableCopy” (na przykład aloc, newObject lub mutableCopy) lub jeśli go wyślesz zachowaj wiadomość.
- Używasz wydania lub automatycznego wydania, aby zrzec się prawa własności do obiektu. autorelease oznacza po prostu „wyślij wiadomość o wydaniu w przyszłości” (w szczególności: gdy używana pula autorelease otrzyma wiadomość o drenażu).
Aktualizacja:
Jak zauważył Josh, jedynym przypadkiem, który należy wziąć pod uwagę, jest to, że globalna i indexPath są takie same. W takim przypadku nadal będziesz „potrzebował” wskaźnika (do wykonania kopii), więc albo automatycznie zwalniasz (zamiast zwalniania) albo używasz tymczasowej zmiennej do obsługi tego.
To, co robisz, jest zasadniczo poprawne, o ile global
ma albo starą wartość, której już nie potrzebujesz, albo jest nil
. Jeśli jest to jeden z ivarów klasy, podczas tworzenia instancji klasy będzie to nil
. Jedyny haczyk polega na tym, że jeśli nowy indexPath
okaże się tym samym obiektem, co ten, który jest już w global
, uwolnisz go nadmiernie i ulegnie awarii.
// global points to object at 0x8BADFOOD
// indexPath also happens to be 0x8BADFOOD; for some reason, it
// hasn't changed since last time. This _can_ happen.
[global release]; // object at 0x8BADFOOD is deallocated
global = [indexPath copy]; // indexPath no longer valid!
// Crash! Bang! Boom!
Sposobem na uniknięcie tego jest użycie zmiennej temp.
Kiedy deklarujesz właściwość jako copy
i syntetyzujesz tę właściwość, tworzona metoda ustawiająca wygląda zasadniczo tak i możesz zrobić to samo:
- (void)setMyFloozit:(Floozit *)newFloozit {
// Copy first in case newFloozit and myFloozit are for
// some reason the same object
// Take ownership of a copy of newFloozit
Floozit * tmp = [newFloozit copy];
// We no longer need old value of myFloozit, so we release it.
[myFloozit release];
// tmp contains a value that we own, we just need to assign
// it to the correct name.
myFloozit = tmp;
}
Można to nieco poprawić, sprawdzając najpierw, czy newFloozit
i myFloozit
są takie same, i nie robiąc nic, jeśli są.
Podobne pytania
Nowe pytania
iphone
NIE używaj tego znacznika, chyba że adresujesz konkretnie iPhone'a i / lub iPoda touch firmy Apple. W przypadku pytań niezależnych od sprzętu użyj tagu [ios]. Więcej tagów do rozważenia to [xcode] (ale tylko jeśli pytanie dotyczy samego IDE), [swift], [objective-c] lub [cocoa-touch] (ale nie [cocoa]). Proszę powstrzymać się od pytań dotyczących iTunes App Store lub iTunes Connect. Jeśli używasz języka C #, oznacz tagiem [mono].
retain
, czy też za pomocą alloc, new, copy lub mutableCopy). Kiedy już go nie potrzebujesz,release
to. Po prostu zastanów się, kiedy z tym skończysz i wtedy możesz to uwolnić.