2012-06-04 26 views
2

我很困惑一个奇怪的事情....我有一个无符号字符数组....我使用calloc分配它,并记录一些字节数据...但是当我释放这个无符号字符并再次分配,我发现它保留了前一次分配的内存中的相同地址。我明白为什么......但我不明白为什么我第二次尝试写入的数据没有被写入......写入了第一次写入的数据......有人可以解释我吗? ??????无符号字符分配和免费问题

unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));

这是我如何分配它.... 其实我的问题是,由于这种分配,其中发生一次,每2秒我有内存泄漏......但是,当我尝试释放的分配的内存部门发生上述事情.... :(

请,如果有人能帮助我....我会很高兴... 这里是代码...

- (unsigned char*) createBitmapContext:(UIImage*)anImage{ 

CGImageRef imageRef = [anImage CGImage]; 
NSUInteger width = CGImageGetWidth(imageRef); 
NSUInteger height = CGImageGetHeight(imageRef); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char)); 
bytesPerPixel = 4; 
bytesPerRow = bytesPerPixel * width; 

NSUInteger bitsPerComponent = 8; 
CGContextRef context = CGBitmapContextCreate(rawData, width, height, 
              bitsPerComponent, bytesPerRow, colorSpace, 
              kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

CGColorSpaceRelease(colorSpace); 
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 

CGContextRelease(context); 

imageRef=nil; 
return rawData; } 

在这个代码中没有这个部分我在那里免费(rawData),因为我不能释放它在这个方法里面,我试图在调用这个方法后全局定义rawData并释放它...但没有什么有趣的...。 ...我会很高兴...

+0

您将需要提供一个完整的代码片段,显示分配和缓冲区写入,以及如何验证内容。以上是不足以回答你的问题。 – gavinb

+0

@gavinb完成...任何有趣的想法? – Garnik

回答

1

好的,所以这种方法是渲染一个UIImage到新分配的字节缓冲区并返回缓冲区给调用者。由于您使用calloc进行分配,因此它将被初始化为0,然后被图像内容覆盖。

当我释放此无符号的字符,然后重新分配,我看到它保留其被分配前一次

在内存中的同一地址

是的,有没有关于缓冲区的位置保证在记忆中。假设您在返回的内存上调用free(),请求完全相同的大小很可能会给您返回相同的缓冲区。但是 - 你如何验证内容不会被第二次写入?什么在缓冲区中?

我的问题是,由于这种分配,其中发生一次,每2秒我有内存泄漏的......但是当我尝试释放所分配的内存部门发生上述事情.... :(

如果发生泄漏,很可能是调用此方法的代码,因为这里没有明显的泄漏,语义显然是这样的,调用者负责释放缓冲区,那么这是如何实现的?

此外,您是否验证CGBitmapContext正在创建?可能是这样我创建标志或参数可能会导致错误。因此,添加context有效的支票(至少不是零)。这可以解释为什么内容没有被覆盖。

一个简单的方法,以确保你的记忆被新鲜更新是您自己的数据写入。您可以用计数器填充缓冲区,并在方法外验证。通过写0-255到缓冲区,您可以轻松地验证

static unsigned updateCounter = 0; 
memset(rawData, updateCounter & 0xff, width*height*4); 

这将循环:例如,刚刚返回rawData之前。

另一件事 - 你想用这段代码实现什么?可能有更简单的方法来实现你想要达到的目标。返回没有元数据的裸缓冲区不一定是管理图像的最佳方式。

+0

我的项目的目标是编写屏幕共享工具。使用这种方法,我想获得像素颜色并与以前的图片进行比较以获得相似度。然后在其他方法中,我得到这两个图片的差异,并发送改变的部分。所有这些部分都完成了,但我有这个泄漏。我确信,因为我每次都会得到下一张照片。而且我也尝试将内存设置为零memset(rawData,0,weight * height * 4);我释放它之后,但仍然是一样的。我明白为什么它每次都返回相同的地址,但我不明白为什么CGBitmapContextCreate方法不会覆盖里面的数据。 – Garnik

+0

而且我敢肯定,泄漏是在rawData的分配...检查了百种方法... – Garnik

+0

是啊我知道param的顺序...但这不会帮助我 – Garnik

0

所以家伙,我解决了这个问题......第一件事,我已经改变了createBitmapContext方法本

- (void) createBitmapContext:(UIImage*)anImage andRawData:(unsigned char *)theRawData{ 

CGImageRef imageRef = [anImage CGImage]; 
NSUInteger width = CGImageGetWidth(imageRef); 
NSUInteger height = CGImageGetHeight(imageRef); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
// unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char)); 
bytesPerPixel = 4; 
bytesPerRow = bytesPerPixel * width; 

NSUInteger bitsPerComponent = 8; 
CGContextRef context = CGBitmapContextCreate(theRawData, width, height, 
              bitsPerComponent, bytesPerRow, colorSpace, 
              kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

CGColorSpaceRelease(colorSpace); 
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 

CGContextRelease(context); 
imageRef=nil; 
// return theRawData;} 

然后......除此之外,我错过了一部分,我分配到newRawData和oldRawData本我有两个指针指向相同的内存地址...所以从这里来的问题...我改变这个分配部分这个memcpy(rawDataForOldImage,rawDataForNewImage,newCapturedImage.size.width * newCapturedImage.size.height * 4);并在这里问题解决了....感谢所有