繁体   English   中英

为什么不使用EXC_BAD_ACCESS?

[英]why not EXC_BAD_ACCESS?

我编写了以下代码:

NSString *string = [[NSString alloc] initWithFormat:@"test"];
[string release];

NSLog(@"string lenght = %d", [string length]);
//Why I don't get EXC_BAD_ACCESS at this point?

我应该,应该释放它。 在上次发布之后,retainCount应该为0,为什么不这样呢?

PS我正在使用最新的XCode。

更新:

NSString *string = [[NSString alloc] initWithFormat:@"test"];

NSLog(@"retainCount before = %d", [string retainCount]);// => 1

[string release];

NSLog(@"retainCount after = %d", [string retainCount]);// => 1 Why!?

在这种情况下,框架可能会从NSString *string = [[NSString alloc] initWithFormat:@"test"];返回文字@"test" NSString *string = [[NSString alloc] initWithFormat:@"test"]; 也就是说,它确定文字可以被重用,并在此上下文中重用它。 毕竟,输入与输出匹配。

但是,您不应依赖程序中的这些内部优化,而应遵循引用计数规则和明确定义的行为。

更新资料

大卫的评论使我对此进行了研究。 在我测试的系统上, NSString *string = [[NSString alloc] initWithFormat:@"test"]; 返回一个对象。 您的程序会向一个对象发出消息,该对象应该已经释放,并且不符合不朽字符串状态。

您的程序仍然落入未定义的领域,并且在某些情况下恰好似乎只是作为实现细节的产物而给出正确的结果-或纯粹是巧合。 正如David指出的那样,在发行版和日志之间添加'stuff'可能会导致string真正被破坏并可能被重用。 如果您真的想知道这一切为何起作用,则可以阅读objc运行时源或在运行时的程序集执行时对其进行爬网。 其中一些可能有解释(运行时实现的详细信息),而另一些纯粹是巧合。

对已发布的对象执行操作是未定义的行为。 含义-有时您无法使用它,有时它崩溃,有时它在一分钟后崩溃在一个完全不同的位置,有时一个十个变量的变量被神秘地修改了。

要捕获这些问题,请使用NSZombie技术。 查一下 那,和一些编码学科。

这次,您离开了,因为释放的内存尚未被任何内容覆盖。 string指向的内存仍然包含长度正确的字符串对象的字节。 一段时间后,将出现其他内容,否则内存地址将不再有效。 而且,这一切都不会发生。

但是,将消息发送到nil对象是合法的。 实际上,这是在目标C中定义的行为-没有任何反应,返回0或nil。

更新:

好。 我很累,没有仔细阅读您的问题。

你没有崩溃的原因是纯粹的运气 最初我虽然使用的是initWithString:在这种情况下,所有有关字符串文字的答案(包括我的原始答案(在下面))都是有效的。


我的意思是“纯粹的运气”

起作用的原因仅仅是释放了对象,但指针仍然指向它曾经所在的位置,并且在您再次读取它之前不会覆盖内存。 因此,当您访问变量时,您将从未修改的内存中读取数据,这意味着您将获得有效的对象。 这样做非常危险, 将来最终会导致崩溃!

如果您开始在发行版和日志之间创建更多对象,则它们中的一个可能会使用与字符串相同的内存,然后在尝试读取旧内存时会崩溃。

它是如此脆弱,以至于连续两次调用log会导致崩溃。


原始答案:

字符串文字永远不会被释放!

请看一下这个问题的回答 ,以说明原因。

这个答案也有很好的解释。

一种可能的解释:您多余地动态分配了一个字符串,而不仅仅是使用常量。 可能Cocoa已经知道这只是浪费内存(如果您不创建可变字符串),因此它可能会释放分配的对象并返回常量字符串。 在恒定的字符串上,释放和保留均无效。

为了证明这一点,值得将返回的指针与常量字符串本身进行比较:

int main()
{
    NSString *s = @"Hello World!";
    NSString *t = [[NSString alloc] initWithFormat:s];

    if (s == t)
        NSLog(@"Strings are the same");
    else
        NSLog(@"Not the same; another instance was allocated");

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM