2011-07-30 10 views
6

en mi aplicación puedo crear un puntero char sin signo utilizando esta función:C y Objective-C - Forma correcta para liberar un puntero unsigned char

- (unsigned char*)getRawData 
{ 
// First get the image into your data buffer 
CGImageRef image = [self CGImage]; 
NSUInteger width = CGImageGetWidth(image); 
NSUInteger height = CGImageGetHeight(image); 

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

unsigned char *rawData = malloc(height * width * 4); 
NSUInteger bytesPerPixel = 4; 
NSUInteger bytesPerRow = bytesPerPixel * width; 
NSUInteger bitsPerComponent = 8; 
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
CGColorSpaceRelease(colorSpace); 

CGContextSetBlendMode(context, kCGBlendModeCopy); 

CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), image); 
CGContextRelease(context); 

// Now your rawData contains the image data in the RGBA8888 pixel format. 

return rawData; 
} 

Y en otra clase asigno una propiedad para ese indicador como tal : self.bitmapData = [image getRawData];

¿Dónde en este proceso puedo liberar esa memoria malloc'd? Cuando trato de liberar la propiedad en dealloc, me da un error exc_bad_access. Siento que me falta un concepto fundamental de c o objetivo c aquí. Toda la ayuda es apreciada.

+0

¿Cómo está liberando la propiedad? – iandotkelly

+1

Cada asignador tiene un desasignador emparejado * para * el objeto asignado. Si mira la página de manual de ['malloc'] (http://linux.die.net/man/3/malloc), pero es la mejor para encontrar la documentación relacionada con su plataforma específica, se explicará qué se debe usar. ;-) –

+0

Probé gratis (propiedad) lo cual no parece correcto, pero de todos modos lo aprobé. –

Respuesta

6

Hay una buena discusión sobre la seguridad de usar malloc/free en el objetivo-c here.

Siempre y cuando libere correctamente() la memoria que malloc(), no debería no hay problema.

Personalmente creo que usar NSMutableData o NSMutableArray es simplemente más fácil. Si no necesita un rendimiento máximo, no usaría las declaraciones C malloc/free directamente.

+0

Eso me ayudó a llegar a la respuesta que en realidad no estaba relacionada con mi uso de forma gratuita. Usando libre (self.property); era incorrecto. * facepalm *. Intenté gratis (propiedad); que funciona bien En el futuro, creo que usaré NSData para evitar la molestia de malloc. –

4

Una forma de evitar este tipo de problema es utilizar NSMutableData, para que pueda reemplazar

unsigned char *rawData = malloc(height * width * 4); 

con

myData = [[NSMutableData alloc] initWithCapacity:height * width * 4]; 
unsigned char *rawData = myData.mutableBytes; 

a continuación, puede liberar myData en su deallocator.

Alternativly que puede hacer

myData = [NSMutableData dataWithCapacity:height * width * 4]; 

Esto entonces significa que su myData se mantiene en torno a la duración del ciclo de eventos, se puede, por causa incluso cambiar el tipo de retorno de método getRawData para volver NSMUtableData o NSData, y de esa manera puede ser retenido por otras partes de tu código, la única vez que devuelvo bytes sin formato en mi código es si sé que estará disponible durante la vida del objeto que lo devuelve, de esa manera si Necesito retener los datos, puedo retener la clase de propietario.

de Apple utilizará a menudo el patrón

myData = [[NSMutableData alloc] initWithCapacity:height * width * 4]; 
unsigned char *rawData = myData.mutableBytes; 

y luego documentar que si necesita los bytes más allá del ciclo actual piscina autorelease a continuación, tendrá que copiarlo.

+0

¿Pero no es ese el mismo problema, justo ahora con un objeto en lugar de un puntero sin formato? El objeto debe ser liberado, el puntero sin formato debe ser liberado. En ambos casos, el diseño debe ser tal que quede bastante claro cuándo pueden descartarse. –

+0

Es más fácil tratar con un objeto porque puede seguir las reglas de retención/liberación.Si devuelve bytes brutos de un método, ¿cómo sabe que la persona que llama del método gestiona la memoria correctamente? ¿Qué sucede si el llamante del método no está interesado en los bytes devueltos? Si los bytes se devuelven desde un método privado, entonces puedes hacer lo que quieras, pero si es parte de la interfaz pública, entonces hacer las cosas a prueba de idiotas para que no tengas que recordar ese método que escribiste hace 6 meses no lo hace comportarse de la manera habitual, es mucho más simple apegarse a un conjunto simple de reglas. –

+0

Es por eso que no ** devolvió ** memoria. Le diría a la persona que llama qué tan grande debe ser y luego la persona que llama puede pasar un buffer que le asignó. Usted acaba de llenar el búfer. De esa forma, la propiedad es mucho más clara, IMO. –

Cuestiones relacionadas