Должен ли быть выпущен результат CGImageGetColorSpace (изображение)?

Я масштабирую CGImageRef. Я нашел несколько примеров кода в Интернете, которые начинаются так:

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

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

CGColorSpaceRelease(colorspace); // Really?

Как вы можете видеть выше, освобождается colorspace. Однако, когда я делаю это, мой код работает большую часть времени, но время от времени происходит сбой, потому что иногда этот экземпляр цветового пространства уже ушел. В документах API говорится:

Вы несете ответственность за сохранение и освобождение цветового пространства по мере необходимости.

Означает ли это, что я должен его освободить? Я предположил, что соглашение состоит в том, что только результаты вызовов с "Create" в имени возвращают объекты, которые должны быть явно выпущены. Означает ли это, что примеры в Интернете просто ошибочны, если вы отпустите CGColorSpaceRef?

Ответ 1

Как говорят документы API, вы несете ответственность за сохранение и освобождение цветового пространства по мере необходимости. То есть если вам нужно, сохраните его. Если вы не сохраните, не отпускайте. Подробнее об этом читайте здесь

Ответ 2

Обратите внимание, что кажется возможным получить сбой при выпуске объекта цветового пространства. Я сделал рытье, но не смог выяснить причину аварии.

У нас есть приложение, которое считывает поля из цветового пространства каждого растрового изображения, с которым оно связано, и будет вызывать [UIImage imageName], а затем CGImageGetColorSpace, за которым следует CGColorSpaceRelease. И в определенном scenerio, он будет делать это несколько раз подряд для одного и того же изображения. Недетерминистически это иногда приводило к сбою со следующей ошибкой во время CGColorSpaceRelease:

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

Это было на iOS5 на ipad и sim.

Я знаю, это худший отчет об ошибке, но, если вы столкнетесь с той же проблемой и начнете вытягивать свои волосы (мы это сделали), то, возможно, это может служить подтверждением того, что вы не единственные человека, который когда-либо сталкивался с этим поведением.

Эта ошибка: "случайный сбой при выполнении тестов соответствия WebGL" кажется, что это может быть та же проблема. Или этот.

Наш обходной путь состоял в том, чтобы перестать читать данные цветового пространства. Все еще не совсем уверен, что происходит не так. Извините, я хотел бы дать больше информации

--- Дэйв

p.s., http://xkcd.com/979/, и извините за сообщение "here be dragons".:)

Ответ 3

То же самое было со мной. Я узнал, что в моем случае проблема заключалась в выпуске следующего ColorSpace:

CGColorSpaceRef colorSpace = CGImageGetColorSpace(pic.CGImage);

После того, как я изменил эту строку на:

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

все по-прежнему работало, за исключением ошибки:)

Ответ 4

Правило для управления жизненными циклами объектов CoreFoundation и других объектов, таких как они, например, объекты CoreGraphic, состоит в том, что если вы получили объект с помощью функции с Create или Copy в своем имени, вам необходимо использовать соответствующий выпуск метод, когда вы закончили с объектом.

Так как код исходного вопроса показывает, что объект CoreGraphics был получен с использованием метода с Get в его имени, а не Create или Copy, тогда вы НЕ должны выпускать объект после его использования. Если вы выпустили, вы должны ожидать сбоев.

Ответ 5

Да, вам нужно.

Возвращаемый CGColorSpaceRef из CGImageGetColorSpace не сохраняется, как предполагает его "Get" в имени. И тогда ваш звонок вызывается CGColorSpaceRetain(colorSpace) или нет.

Тем не менее, я сильно призываю вас сделать это (и, позднее, конечно же, выпустить), если вы намереваетесь делать что-нибудь полезное с этим цветовым пространством (например, создайте градиент или что-то еще). Если вы этого не сделаете, вы предложите себе кошмар случайных сбоев в различных функциях CG.

Если вам нужно, чтобы какой-то объект CG передавался на некоторые другие функции, всегда делайте это, чтобы он сохранялся. Всегда.