我在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函数时,其他东西写在同一个内存中。结果每次都不同,但数据永远不会持久。
当我告诉调试器在这些地址发生变化时暂停时,我最终会在汇编代码中找到我不能做任何事情的代码。
我应该如何以及在何处分配内存空间,以便程序的其余部分不会愚弄它?
答案 0 :(得分:2)
问题是你没有拥有名为data的变量,并且几乎肯定会在你第一次点击自动释放池排放时被解除分配(或者如果你使用的是GC,它会在超出范围后消失)。当data
消失时,您正在仔细创建指向[data bytes]
的所有指针都会悬空。
在引用计数环境中,您需要在自动释放池耗尽之前将-retain
发送到data
(保证在您返回运行循环时发生),然后您需要释放当你完成其中的数据时。在GC环境中,您只需要保留一个强大的参考,例如把它变成某种物体的伊娃。
或者,您可以将数据复制到其他位置,而不是仅创建指向其位的指针。
答案 1 :(得分:0)
抱歉,我还不能发表评论,所以这里有一个完整的答案:
就像杰里米说的那样,你没有data
的引用,所以它会消失!
然而,有几种方法可以确保它的可行性:
data
(我的意思是指针!),这样你就可以在使用它时释放它。__strong void *
或(因为NSData
免费桥接到CFData
)调用CFRetain( (CFDataRef) data )
is actually not a noop in GC-ed code ! (这已经涵盖了GC-ed 和重新计算的环境BTW ......)[[NSData alloc] initWithContentsOfFile:]
创建该对象并将其存入您的结构中。 (GC-notes也适用于此处!)malloc
您图片的记忆,然后使用-[NSData getBytes:range:]
但这可能意味着一个明显的性能影响。无论您选择哪种方式,都不要忘记自己清理 - CFRelease()
可能是案例1和案例2中最好的解决方案,因为它涵盖了GC和重新计数。
NSFileHandle
而不是直接通过NSData
- 方法?NSKeyedArchiver
将它存储为二元plist,并且比通过指针体操检索它更优雅,而且开销很小。哦,大一点:
你正在做什么/尝试做什么正好:
// IMAGE 1
organizedImageData->image1Data = (UInt8 *)rawData;
rawData++;
// IMAGE 2
organizedImageData->image2Data = (UInt8 *)rawData;
rawData++;
我无法理解这一点 顺便提一下,建议2可能会简化这一点: - )