【问题标题】:Analyzer claiming an object was released when it wasn't声称对象已被释放的分析器
【发布时间】:2012-08-18 21:04:36
【问题描述】:

我在这段代码中遇到了一个静态分析错误,这对我来说没有任何意义。错误是:

引用计数对象释放后使用

这是允许在最初用 C++ 编写的游戏中加载 PNG 的胶水代码。

int pngLoad(const char *filename, pngInfo *info, int format, GLuint *textureName)
{
    char fullPath[Engine::Settings::MaxPath];
    strcpy(fullPath, filename);
    appendAppBundlePath(fullPath);

    NSString *path = [NSString stringWithCString:fullPath encoding:NSUTF8StringEncoding];
    NSData *data = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:data];
    [data release];

    Texture2D *loadedTex = [Texture2D alloc];

    // ##### Analyzer claims the object is released here: #####
    [loadedTex initWithImage:image format:format];

    int didLoad;

    // ##### Error is here: #####
    if (loadedTex.contentSize.width == 0 || loadedTex.contentSize.height == 0)
    {
        didLoad = 0;
    }
    else
    {
        didLoad = 1;

        *textureName = loadedTex.name;

        // return texture info
        info->ScaleFactor = loadedTex.scaleFactor;
        info->Width = (float)image.size.width / (float)info->ScaleFactor;
        info->Height = (float)image.size.height / (float)info->ScaleFactor;
        info->Alpha = 1;
        info->PaddedWidth = loadedTex.pixelsWide;
        info->PaddedHeight = loadedTex.pixelsHigh;
    }

    [loadedTex release];
    [image release];

    return didLoad;
}

如果我使用Texture2D *loadedTex = [[Texture2D alloc] retain];,此警告将被删除,但随后会出现我已泄漏对象的警告,所以这里有些事情很奇怪。

initWithImage:format: 曾经包含一个不应该存在的[self release],当我发现这个警告时我删除了它。但是,即使在完全清理和重建之后,我仍然会收到警告。我做错了什么吗? Xcode 中的 Clean 命令是否没有正确清理某些内容?

【问题讨论】:

    标签: objective-c ios xcode memory-management objective-c++


    【解决方案1】:

    分析者可能是对的,至少在一般情况下是这样。

    Texture2D *loadedTex = [Texture2D alloc];
    [loadedTex initWithImage:image format:format];
    

    一般来说,“init”实际上可能会丢弃传入的对象并返回一个不同的对象。我不知道“Texture2D”是否属于这种情况,但如果分析仪适用于一般情况,那么它是正确的。

    你应该可以通过使用来解决这个问题

    Texture2D *loadedTex = [Texture2D alloc];
    loadedTex=[loadedTex initWithImage:image format:format];
    

    或者通过简单地组合这两个调用,就像在大多数 Objective-C 示例中所做的那样。

    【讨论】:

    • 我想知道这是否是我的纹理加载中另一个奇怪的错误的原因。在罕见的随机情况下,我让一个对象从关卡中的另一个对象中获取纹理。如果这不能解决问题,我稍后可能会在单独的问题中询问这个问题。不过这不太可能,因为我在Texture2D 类中看不到任何丢弃对象并返回不同对象的代码。它是旧苹果 CrashLanding 示例中 Texture2D 的修改版本。
    • 这仍然可能是问题所在,具体取决于超类的功能。如果 Texture2D 是从 NSObject 派生的,那么它不会做任何“丢弃并返回不同的”;我知道苹果在某些情况下特别提到了它,但我不知道他们是否总是提到它。所以,最好假设它会发生
    • 作为一个稍微相关的后续,原来我提到的罕见错误是由某些 C++ 代码中未初始化的 C 字符串引起的。垃圾数据有时会包含来自先前加载的图像的数据,从而导致一些非常时髦的问题。
    【解决方案2】:

    在这种情况下,您应该始终在创建对象时结合使用 allocinitXXX 调用

    Texture2D *loadedTex = [[Texture2D alloc] initWithImage:image format:format];
    

    init 方法不必返回与调用它的对象相同的对象,它可以返回不同的对象。

    在这种情况下,您来自 loadedTex = [Texture2D alloc] 的结果将被释放,initWithImage 将返回一个不同的对象(您将其丢弃)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-31
      • 2013-11-19
      相关资源
      最近更新 更多