Does the result of CGImageGetColorSpace(image) have to be released?
Asked Answered
B

5

9

I'm scaling a CGImageRef. I found various code examples on the web that begin like so:

CGColorSpaceRef colorspace = CGImageGetColorSpace(image); // "Get" color space

CGContextRef context = CGBitmapContextCreate(NULL, width, height,
    CGImageGetBitsPerComponent(image),
    CGImageGetBytesPerRow(image),
    colorspace,
    CGImageGetAlphaInfo(image));

CGColorSpaceRelease(colorspace); // Really?

As you can see above, the colorspace is released. However, when I do that my code works most of the time, but crashes once in a while, because sometimes that colorspace instance is already gone. The API docs say:

You are responsible for retaining and releasing the color space as necessary.

Does that mean I must release it? I assumed the convention was that only results of calls with "Create" in the name return objects that have to be released explicitly. Does this mean the examples on the web are simply wrong when releasing that CGColorSpaceRef?

Bookmobile answered 11/3, 2011 at 6:43 Comment(0)
A
11

As the API docs say, you are responsible for retaining and releasing the color space as necessary. I.e. if you need, retain it. If you do not retain, don't release. Read more about it here

Absolution answered 11/3, 2011 at 6:57 Comment(1)
Yeah, seems like it. Here is the Apple documentation about get/create for Core Foundation: linkAbsolution
W
3

Note that it seems possible to get a crash from releasing the colorspace object. I did some digging, but was unable to ascertain the root cause of the crash.

We have an app that was reading fields from the colorspace of each bitmap it dealt with and would call [UIImage imageName] followed by CGImageGetColorSpace followed by CGColorSpaceRelease. And in a certain scenerio, it would do this multiple times in a row for the same image. Non-deterministically, this would sometimes crash with the following error during the CGColorSpaceRelease:

Assertion failed: (!state->is_singleton), function color_space_state_dealloc, file ColorSpaces/CGColorSpace.c, line 127.

This was on iOS5 on both the ipad and the sim.

I know, this is the worst kind of bug report, but hey, if you run into the same issue and start pulling your hair out (we did), then perhaps this can serve as confirmation that you aren't the only person to ever hit this behavior.

This bug: "random crash while running WebGL conformance tests" seems like it might be the same issue. Or this one.

Our workaround was to stop reading the colorspace data. Still not quite sure what was going wrong. Sorry, wish I could give more info

--- Dave

p.s., http://xkcd.com/979/, and sorry for the "here be dragons" post. :)

Washday answered 14/2, 2012 at 7:38 Comment(2)
I was getting this in a very repeatable manner on an iOS 5.x device, and not at all on a iOS 6 device with the exact same code. So it appears this MIGHT be fixed on iOS 6. (this was with an ARC-enabled project, if that matters) +1 for the xkcd reference.Kramatorsk
I have been experiencing exactly the same problem on iOS 7 both beta and GM. Please provide any information that you have found on how to fix this until now. ThxFourinhand
A
3

The same problem used to happen to me. I found out, that in my case the problem was the releasing the following ColorSpace:

CGColorSpaceRef colorSpace = CGImageGetColorSpace(pic.CGImage);

After i changed that line to:

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

everything worked as before, except of the error :)

Alcoran answered 30/7, 2012 at 10:29 Comment(2)
That was my issue (in iOS 5, iOS 6 seemed to work fine). Thanks for the pointer - saved me lots of aggravation!Kramatorsk
The way things are named in Cocoa means a lot. Your first line used "Get" which does not imply ownership, so the returned CGColorSpaceRef is not retained. You need to do that. The second line has "Create" which implies it will be retained, thus you don't need to do that.Rattat
P
3

The rule for managing CoreFoundation objects lifetimes and other objects like them e.g., CoreGraphic objects is that if you have obtained the object using a function that has Create or Copy in its name then you need to use the appropriate release method when you have finished with the object.

Since the code in the original question shows that the CoreGraphics object was obtained using a method with Get in its name and not Create or Copy then you should NOT release the object after using it. If you do release you should expect to get crashes.

Panthea answered 23/2, 2014 at 11:36 Comment(0)
R
1

Yes, you have to.

The returned CGColorSpaceRef from CGImageGetColorSpace is not retained, as its "Get" in the name implies. And it's your call will you then call CGColorSpaceRetain(colorSpace) or not.

However, I strongly urge you to do that (and later release, of course) if you intend to do anything useful with that color space (say create a gradient or something). If you do not, you will invite yourself to a nightmare of random crashes in various CG functions.

If you need some CG object to be passed to some other functions, always make sure it's retained. Always.

Radiancy answered 6/9, 2014 at 14:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.