我的调试器要么破坏,要么有一些我不理解的基本内容。

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

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。

我看到了与其他类别的类似行为 NSURLNSNumber. 。但是有些课程崩溃了,例如 NSErrorNSObject.

这与班级集群有关吗?对于内存管理,他们是否遵守相同的规则?

如果类别簇与此问题无关,我可以看到的唯一其他常见功能是,以这种方式崩溃的类都是与核心基础相对方的免费桥接。这可能与它有关吗?

有帮助吗?

解决方案

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

在这种情况下,

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

只是返回与 @"Hello" 作为优化。常数 NSString 永远不会被划分;作为优化, retainrelease (我认为)被忽略。这就是为什么它不会崩溃。

您可以通过比较指针值来检查我的猜测 @"Hello"string.

其他提示

这是一个很好的例子,说明为什么保留计数是一种毫无用处的调试工具。假设 - 固定和 - 弹力始终从保留计数中添加或删除1是一个错误,并且您认为保留计数是您认为应该是的。

尝试

NSString *string = [[NSString alloc] initWithFormat:@"Hello %d", argc];

这应该给您一个琴弦,它的行为会更像您期望的方式,因为您没有从编译时间常数初始化字符串。但是,请注意,通过启用僵尸,您将获得您期望的行为,但是如果没有僵尸,NSLOG可能会起作用。尽管该字符串已被划定,但对象中的数据仍在存储器中,留下了“幽灵”,该数据将正确响应某些消息。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top