objective-c - *应该*崩溃的简单 Objective-C 过度发布不会崩溃。为什么?

标签 objective-c debugging memory-management crash foundation

要么我的调试器坏了,要么有一些我不理解的基本知识。

我在一个非常基本的命令行程序中有一些非常基本的代码应该崩溃。但是,它并没有崩溃。

int main (int argc, const char * argv[])
{
    NSString *string = [[NSString alloc] initWithString:@"Hello"];

    [string release];

    NSLog(@"Length: %d", [string length]);

    return 0;
}

日志语句打印“Length: 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。

我看到其他类的行为类似,例如 NSURLNSNumber。但是有些类会按预期崩溃,例如 NSErrorNSObject

这跟类群有关系吗?它们在内存管理方面是否遵循相同的规则?

如果类集群与这个问题无关,我能看到的唯一其他共同特征是不会以这种方式崩溃的类都是免费桥接 Core Foundation 对应类的。这可能与它有关吗?

最佳答案

retain/release 是 API 和程序员之间的契约,当您遵守规则时,它不会崩溃。合约不保证如果你不遵守规则,它就会崩溃!

在这种情况下,

[[NSString alloc] initWithString:@"Hello"]

只是返回与 @"Hello" 相同的对象作为优化。常量 NSString 永远不会被释放;作为优化,retainrelease(我认为)被忽略了。这就是它不会崩溃的原因。

您可以通过比较@"Hello"string 的指针值来验证我的猜测。

关于objective-c - *应该*崩溃的简单 Objective-C 过度发布不会崩溃。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4079198/

相关文章:

javascript - Chrome Javascript 调试器在暂停时不会重新加载页面

如果 case 为 false,尽管换行,Xcode 断点仍会触发

cocoa - appkit 应用程序中的自动释放池

ios - nil 不是用于搜索实体名称 'GroupMessageInfo' 的合法 NSPersistentStoreCoordinator

iphone - 如何按升序比较包含日期的 NSString 数组

ios - Wikitude/AR SDK 用于在 3d 空间中挑选对象

java - android加载图片会分配大内存

iphone - 创建一个包含许多产品的数据库

javascript - 如何在 Ionic 应用程序的 Chrome 远程调试中隐藏内容(API key 等)?

c++ Intel inspector 显示许多 boost 错误 - 我需要担心吗?