结构内存分配(泄漏和崩溃,在iPhone上进行分析)

时间:2014-02-24 18:52:08

标签: objective-c c memory-management struct profiling

我有一个结构定义为:

struct VImage
{
    uint8_t *imageData;
    int dimensions[3];
    ...
}

我正在分析我的代码以查找泄漏和其他问题。请考虑以下代码:

for (int i = 0; i < 100; i++)
{
    // after we have the image, we use the cheap rgb function to get rgb data
    struct VImage *vImage = [SomeClass someFunction:someArgument];
    free(vImage);
}

这会导致我的代码崩溃。我想知道为什么会这样。但条件i < 10不会使应用程序崩溃。对仪器进行分析并未表明存在任何泄漏;然而,分配激增,我使用了大量的实时内存;所以我想知道是否以这种方式释放结构是正确的,或者如果free是一个异步函数,它将释放某人的记忆,但不仅仅是当我要求它时。

编辑:所以我被要求提供这个someFunction方法的详细信息,我会的。我认为该方法没有内存泄漏但是,我会把它放在这里:

+ (struct VImage *)grayScaleImageDataFromImage:(UIImage *)image
{
    int imageWidth = image.size.width, imageHeight = image.size.height;

    uint32_t *rgbImageData = (uint32_t *) malloc(imageWidth * imageHeight * sizeof(uint32_t));
    memset(rgbImageData, 0, imageWidth * imageHeight * sizeof(uint32_t));

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    // create context with RGBA pixels
    CGContextRef context = CGBitmapContextCreate(rgbImageData, imageWidth, imageHeight, 8, imageWidth * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGContextSetShouldAntialias(context, NO);

    // paint to fill pixels array
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), [image CGImage]);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    // now convert to grayscale using CCIR 601 <=> Y' = 0.299 R' + 0.587 G' + 0.114 B'.
    uint8_t *grayScaleImageData = (uint8_t *) malloc(imageWidth * imageHeight);
    for(int y = 0; y < imageHeight; y++)
    {
        for(int x = 0; x < imageWidth; x++)
        {
            uint32_t rgbPixel = rgbImageData[y*imageWidth+x];
            grayScaleImageData[y*imageWidth + x] = 0.299*((rgbPixel>>24)&255) + 0.587*((rgbPixel>>16)&255) + 0.114*((rgbPixel>>8)&255);
        }
    }

    struct VImage *vImage = createGrayScaleDescription(grayScaleImageData, imageHeight, imageWidth);

    free(rgbImageData);
    return vImage;
}

struct VImage *createGrayScaleDescription(uint8_t *grayScaleImage, int height, int width)
{
    struct VImage *vImage = malloc(sizeof(struct VImage));
    vImage->grayScaleImage = grayScaleImage;
    vImage->numberOfDimensions = 2;
    vImage->dimensions[0] = height, vImage->dimensions[1] = width, vImage->dimensions[2] = 1;
    vImage->isGrayscale = true;
    return vImage;
}

所以我所做的就是通过一些计算使用rgb数据创建灰度图像。但是,我认为这里没有任何问题。

1 个答案:

答案 0 :(得分:0)

首先,你正在泄漏grayScaleImageData指向的内存:

在grayScaleImageDataFromImage中你做

uint8_t *grayScaleImageData = (uint8_t *) malloc(imageWidth * imageHeight);

这很好,然后在createGrayScaleDescription中设置vImage->grayScaleImage以指向该内存,这也很好。

但是在你的1到100循环中,你释放vImage而不首先释放vImage->grayScaleImage指向的内存。那是内存泄漏。

我认为不应该崩溃你的应用程序,但这是你需要解决的问题。没有别的东西跳出来,但我会仔细看看。

编辑:仔细检查后,您似乎超出了分配给的缓冲区  grayScaleImageData

你用以下方式进行游戏:

uint8_t *grayScaleImageData = (uint8_t *) malloc(imageWidth * imageHeight);

然后用:

填充缓冲区
uint32_t rgbPixel = rgbImageData[y*imageWidth+x];
grayScaleImageData[y*imageWidth + x] = 0.299*((rgbPixel>>24)&255) + 0.587*((rgbPixel>>16)&255) + 0.114*((rgbPixel>>8)&255);

你已经分配了(imageWidth * imageHeight)8位uints,但是你用32位uints填充它。

也许这就是导致你崩溃的原因?也许尝试将malloc更改为

uint32_t *grayScaleImageData = (uint32_t *) malloc(imageWidth * imageHeight * sizeof (uint32_t));

就像你上面为rgbImageData做的那样?在将其设置为grayScaleImageData之前,将您的位移计算结果转换为uint8_t:

uint32_t rgbPixel = rgbImageData[y*imageWidth+x];
grayScaleImageData[y*imageWidth + x] = (uint8_t)(0.299*((rgbPixel>>24)&255) + 0.587*((rgbPixel>>16)&255) + 0.114*((rgbPixel>>8)&255));