gpt4 book ai didi

iphone - 如何解决iphone开发中遇到的EXC_BAD_ACCESS错误

转载 作者:太空狗 更新时间:2023-10-30 03:16:56 25 4
gpt4 key购买 nike

我正在尝试做一件简单的事情;从互联网上读取图像,将其保存到 iphone 上应用程序的文档目录,然后从该文件中读取它,以便我以后可以用它做其他事情。写入文件工作正常,但是当我尝试读回它时,我在 GDB 中收到 EXC_BAD_ACCESS 错误,我不知道如何解决。这是我的代码基本上的样子:

-(UIImage *) downloadImageToFile {
NSURL * url = [[NSURL alloc] initWithString: self.urlField.text];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

[paths release]
NSString * path = [documentsDirectory stringByAppendingString:@"/testimg.png"];

NSData * data = [[NSData alloc] initWithContentsOfURL:url];

[data writeToFile:path atomically:YES];

return [[UIImage alloc] initWithContentsOfFile:path];
}

当我尝试从文件初始化 UIImage 时,代码在 return 语句中失败。有任何想法吗?

编辑 : 忽略了添加最初是代码中存在问题的版本。

最佳答案

注:这特别适用于 非 ARC 内存管理。

由于这有如此多的观点,并且检查的答案适本地指出“代码显示严重缺乏对 Objective-C 中内存管理工作方式的了解”,但没有人指出具体的错误,我想我会添加一个触及他们的答案。

关于调用方法,我们必须记住的基线级别规则:

  • 如果方法调用包含单词 分配 , 新品 , 复制 , 或 保留 , 我们拥有创建的对象的所有权。¹ 如果我们拥有一个对象的所有权,我们有责任释放它。
  • 如果方法调用不包含这些词,我们就没有所创建对象的所有权。¹如果我们没有对象的所有权,释放它不是我们的责任,因此我们永远不应该这样做。

  • 让我们看看 OP 代码的每一行:
    -(UIImage *) downloadImageToFile {

    我们开始了一种新方法。在这样做的过程中,我们启动了一个新的上下文,每个创建的对象都存在于其中。请记住这一点。下一行:
        NSURL * url = [[NSURL alloc] initWithString: self.urlField.text];

    我们拥有 url : 字 分配那里告诉我们我们拥有对象的所有权,我们需要自己释放它。如果我们不这样做,那么代码将泄漏内存。
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    我们不拥有 paths : 没有使用四个魔法词,所以我们没有所有权,绝对不能自己释放它。
        NSString *documentsDirectory = [paths objectAtIndex:0];

    我们不拥有 documentsDirectory : 没有魔法词 = 没有所有权。
        [paths release]

    返回几行我们看到我们不拥有 路径 ,因此当我们尝试访问不再存在的内容时,此版本将导致 EXC_BAD_ACCESS 崩溃。
        NSString * path = [documentsDirectory stringByAppendingString:@"/testimg.png"];

    我们不拥有 path : 没有魔法词 = 没有所有权。
        NSData * data = [[NSData alloc] initWithContentsOfURL:url];

    我们拥有 data : 字 分配那里告诉 use 我们拥有对象的所有权,我们需要自己释放它。如果我们不这样做,那么代码将泄漏内存。

    以下两行不会创建或释放任何内容。然后是最后一行:
    }

    该方法已结束,因此变量的上下文已结束。查看代码,我们可以看到我们同时拥有 urldata ,但没有释放它们中的任何一个。因此,每次调用此方法时,我们的代码都会泄漏内存。
    NSURL对象 url不是很大,所以我们可能永远不会注意到泄漏,虽然它仍然应该清理,但没有理由泄漏它。
    NSData对象 data是一个 png 图像,并且可能非常大;每次调用此方法时,我们都会泄漏对象的整个大小。想象一下,每次绘制表格单元格时都会调用它:整个应用程序崩溃根本不会花很长时间。

    那么我们需要做些什么来解决这些问题呢?这很简单,我们只需要在不再需要对象时立即释放它们,通常是在最后一次使用它们之后:
    -(UIImage *) downloadImageToFile {

    // We own this object due to the alloc
    NSURL * url = [[NSURL alloc] initWithString: self.urlField.text];

    // We don't own this object
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    // We don't own this object
    NSString *documentsDirectory = [paths objectAtIndex:0];

    //[paths release] -- commented out, we don't own paths so can't release it

    // We don't own this object
    NSString * path = [documentsDirectory stringByAppendingString:@"/testimg.png"];

    // We own this object due to the alloc
    NSData * data = [[NSData alloc] initWithContentsOfURL:url];

    [url release]; //We're done with the url object so we can release it

    [data writeToFile:path atomically:YES];

    [data release]; //We're done with the data object so we can release it

    return [[UIImage alloc] initWithContentsOfFile:path];

    //We've released everything we owned so it's safe to leave the context
    }

    有些人喜欢在方法结束时上下文关闭之前立即释放所有内容。在这种情况下, [url release];[data release];将在收盘前出现 }支撑。我发现如果我尽快释放它们,代码会更清晰,当我稍后再查看它时,我会在我完成对象的地方明确说明。

    总结一下:我们拥有使用 alloc 创建的对象, new , copy , 或 retain在方法调用中,所以必须在上下文结束之前释放它们。我们不拥有其他任何东西,绝不能释放它们。

    ¹这四个词实际上并没有什么神奇之处,它们只是 Apple 创造相关方法的人们一直在使用的提醒。如果我们为自己的类创建自己的初始化或复制方法,那么在其适当的方法中包含单词 alloc、new、copy 或 retain 是我们的责任,如果我们不在我们的名称中使用它们,那么我们需要自己记住所有权是否已经过去。

    关于iphone - 如何解决iphone开发中遇到的EXC_BAD_ACCESS错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/607222/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com