Простая цель - C переоценка, что * следует * Crash не сбивается. Почему?
-
28-09-2019 - |
Вопрос
Либо мой отладчик нарушен, либо есть что-то фундаментальное, что я не понимаю.
У меня есть очень базовый код в очень базовой программе командной строки, которая должен крушение. Тем не менее, это не разрушается.
int main (int argc, const char * argv[])
{
NSString *string = [[NSString alloc] initWithString:@"Hello"];
[string release];
NSLog(@"Length: %d", [string length]);
return 0;
}
Заявление журнала печатает «Длина: 5», поскольку вы ожидаете для действительной строки. Однако строка должна быть оформлена в этой точке и exec_bad_access
Ошибка должна быть брошена.
Я попробовал этот код с прикрепленным отладчиком и без подключенного отладчика - оба дают тот же результат. Я также включен (и отключен) NSZombie
, что, кажется, не имеет никакого эффекта (я изначально подумал, что это проблема, поскольку NSZombie
Объекты никогда не оформлены - но это все еще не врезается с NSZombie
инвалид).
У меня есть точки останова, установленные в моем местном .gdbinit
файл, чтобы сломаться на таких вещах, как -[NSException raise]
а также objc_exception_throw
. Отказ У меня также есть точки останова, установленные на многих методах на NSZombie
чтобы поймать их.
fb -[NSException raise]
fb -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]
fb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
#define NSZombies
# this will give you help messages. Set to NO to turn them off.
set env MallocHelp=YES
# might also be set in launch arguments.
set env NSZombieEnabled=YES
set env NSDeallocateZombies=NO
set env MallocCheckHeapEach=100000
set env MallocCheckHeapStart=100000
set env MallocScribble=YES
set env MallocGuardEdges=YES
set env MallocCheckHeapAbort=1
set env CFZombie 5
fb -[_NSZombie init]
fb -[_NSZombie retainCount]
fb -[_NSZombie retain]
fb -[_NSZombie release]
fb -[_NSZombie autorelease]
fb -[_NSZombie methodSignatureForSelector:]
fb -[_NSZombie respondsToSelector:]
fb -[_NSZombie forwardInvocation:]
fb -[_NSZombie class]
fb -[_NSZombie dealloc]
fb szone_error
fb objc_exception_throw
С этими точками останова и включена Nszombie, я должен получить что-то вроде [NSString length]: message sent to deallocated instance 0x100010d39
напечатано на консоль, но я этого не вижу. Я вижу NSLog
Печать длины как 5.
Я вижу подобное поведение с другими классами, такими как NSURL
а также NSNumber
. Отказ Но некоторые классы аварии, как и ожидалось, такие как NSError
а также NSObject
.
Есть ли у этого есть что делать с классовыми кластерами? Они не следуют тому же правилам в отношении управления памятью?
Если классовые кластеры не связаны с этой проблемой, единственная прочая общая функция, которую я мог видеть, заключалась в том, что классы, которые не сбиваются таким образом, - все бесплатные модифицированные бесплатные с помощью основного фундамента. Может ли это иметь что-то связанное с этим?
Решение
retain
/release
Договор между API и программистом, который, когда вы следите за правилом, он не сбивается. Контракт не гарантирует, что если вы не будете следовать правилу, он работает сбой!
В этом случае,
[[NSString alloc] initWithString:@"Hello"]
просто возвращает тот же объект, что и @"Hello"
как оптимизация. Константа NSString
никогда не освобожден; как оптимизация, retain
а также release
Есть (я думаю) игнорировал. Вот почему это не хватает.
Вы можете проверить свое предположение, сравнивая значение указателя @"Hello"
а также string
.
Другие советы
Это отличный пример того, почему уход за сохранением является довольно бесполезный инструмент отладки. Ошибка предположить -retake и -release всегда добавлять или удалять 1 из удержанного подсчета, и что подсчет сохранения - это то, что вы думаете, что должно быть.
Пытаться
NSString *string = [[NSString alloc] initWithFormat:@"Hello %d", argc];
Это должно дать вам строку, которая будет вести себя больше похоже на то, как вы ожидаете, поскольку вы не инициализируете свою строку из постоянной времени компиляции. Однако следует предупредить, с включенным зомби, вы получите поведение, которое вы ожидаете, но без зомби, NSLog может работать хорошо. Хотя строка была освобождена, данные в объекте все еще там в памяти, оставляя «призрак», который будет правильно отвечать на некоторые сообщения.