正在写入我分配的内存

时间:2010-09-01 14:22:38

标签: objective-c c memory memory-management

我在Objective-C中编写了一个项目,但由于涉及OpenGL,我非常依赖普通的旧C语言。

我有一个数据blob,我通过以下方式从文件中读取内存:

NSString *path = [[NSBundle mainBundle] pathForResource:@"iPadTest" ofType:@""];
NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
data = [file readDataToEndOfFile];
currentImage = [ReadDataFiles getOrganizedImageData:data];

最后一个函数为我提供了一种结构,其中数据更易于访问,但仍有三个冗长的图像数据数据块。它是这样开始的:

ImageData *organizedImageData = malloc(sizeof(ImageData));

// IMAGE DIMENSIONS
UInt64 *rawData = (UInt64 *) data.bytes;
organizedImageData->imageDimensions.x = *rawData;
rawData++;
organizedImageData->imageDimensions.y = *rawData;
rawData++;
organizedImageData->imageDimensions.z = *rawData;

// IMAGE 1
rawData++;
organizedImageData->image1Data = (UInt8*)rawData;
// IMAGE 2
rawData++;
organizedImageData->image2Data = (UInt8*)rawData;

// etc...

问题是当数据到达OpenGL函数时,其他东西写在同一个内存中。结果每次都不同,但数据永远不会持久。

当我告诉调试器在这些地址发生变化时暂停时,我最终会在汇编代码中找到我不能做任何事情的代码。

我应该如何以及在何处分配内存空间,以便程序的其余部分不会愚弄它?

2 个答案:

答案 0 :(得分:2)

问题是你没有拥有名为data的变量,并且几乎肯定会在你第一次点击自动释放池排放时被解除分配(或者如果你使用的是GC,它会在超出范围后消失)。当data消失时,您正在仔细创建指向[data bytes]的所有指针都会悬空。

在引用计数环境中,您需要在自动释放池耗尽之前将-retain发送到data(保证在您返回运行循环时发生),然后您需要释放当你完成其中的数据时。在GC环境中,您只需要保留一个强大的参考,例如把它变成某种物体的伊娃。

或者,您可以将数据复制到其他位置,而不是仅创建指向其位的指针。

答案 1 :(得分:0)

抱歉,我还不能发表评论,所以这里有一个完整的答案:
就像杰里米说的那样,你没有data的引用,所以它会消失!

然而,有几种方法可以确保它的可行性:

  1. 在你的结构中存储data(我的意思是指针!),这样你就可以在使用它时释放它。
    如果您在GC下运行,请将该字段定义为__strong void *或(因为NSData免费桥接到CFData)调用CFRetain( (CFDataRef) data ) is actually not a noop in GC-ed code ! (这已经涵盖了GC-ed 重新计算的环境BTW ......)
  2. 通过[[NSData alloc] initWithContentsOfFile:]创建该对象并将其存入您的结构中。 (GC-notes也适用于此处!)
  3. malloc您图片的记忆,然后使用-[NSData getBytes:range:] 但这可能意味着一个明显的性能影响。
  4. 无论您选择哪种方式,都不要忘记自己清理 - CFRelease()可能是案例1和案例2中最好的解决方案,因为它涵盖了GC和重新计数。


    顺便说一下(我希望这不会像粗鲁一样!) 是否有某种原因......

    1. 您正在使用NSFileHandle而不是直接通过NSData - 方法?
    2. 你的数据是这样的blob吗? 你可以通过NSKeyedArchiver将它存储为二元plist,并且比通过指针体操检索它更优雅,而且开销很小。
    3. 哦,大一点:
      你正在做什么/尝试做什么正好

      // IMAGE 1
      organizedImageData->image1Data = (UInt8 *)rawData;
      rawData++;
      // IMAGE 2
      organizedImageData->image2Data = (UInt8 *)rawData;
      rawData++;
      

      我无法理解这一点 顺便提一下,建议2可能会简化这一点: - )