2011-07-30 8 views
6

trong ứng dụng của tôi, tôi tạo ra một con trỏ char unsigned sử dụng chức năng này:C và Objective-C - Cách thực hiện để giải phóng một con trỏ char unsigned

- (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; 
} 

Và trong lớp khác tôi gán một tài sản để có con trỏ như vậy : self.bitmapData = [image getRawData];

Tôi có thể giải phóng bộ nhớ malloc'd ở đâu trong quá trình này? Khi tôi cố gắng giải phóng tài sản trong dealloc, nó cho tôi một lỗi exc_bad_access. Tôi cảm thấy như tôi đang thiếu khái niệm c cơ bản hoặc mục tiêu c ở đây. Tất cả trợ giúp đều được đánh giá cao.

+0

Bạn giải phóng tài sản bằng cách nào? – iandotkelly

+1

Mỗi người cấp phát có một bộ cấp phát được ghép nối với * miễn phí * đối tượng được phân bổ. Xem trang hướng dẫn cho ['malloc'] (http://linux.die.net/man/3/malloc) - nhưng tốt nhất là tìm tài liệu liên quan đến nền tảng cụ thể của bạn - sẽ giải thích những gì nên được sử dụng ;-) –

+0

Tôi đã cố gắng miễn phí (tài sản) mà không có vẻ chính xác nhưng tôi đã cho nó một đi anyway. –

Trả lời

6

Có một cuộc thảo luận tốt về sự an toàn của việc sử dụng malloc/miễn phí trong mục tiêu-c here.

Miễn là bạn giải phóng chính xác() bộ nhớ mà bạn malloc(), có nên không có vấn đề gì.

Cá nhân tôi nghĩ rằng việc sử dụng NSMutableData hoặc NSMutableArray dễ dàng hơn. Nếu bạn không cần hiệu suất tối ưu, tôi sẽ không sử dụng các câu lệnh C malloc/free trực tiếp.

+0

Điều đó đã giúp tôi đưa ra câu trả lời thực sự không liên quan đến việc sử dụng miễn phí của tôi. Sử dụng miễn phí (self.property); đã sai. * facepalm *. Tôi đã thử miễn phí (tài sản); mà hoạt động tốt. Trong tương lai, tôi tin rằng tôi sẽ sử dụng NSData để tránh những rắc rối của malloc. –

4

Một cách để khắc loại này của vấn đề là sử dụng NSMutableData, vì vậy bạn có thể thay thế

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

với

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

sau đó bạn có thể giải phóng myData trong deallocator của bạn.

alternativly bạn có thể làm

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

này sau đó sẽ có nghĩa là bạn myData được giữ xung quanh thời gian của vòng lặp sự kiện, bạn có thể nguyên nhân thậm chí thay đổi kiểu trả về của getRawData phương pháp để trở lại NSMUtableData hoặc NSData, và theo cách đó nó có thể được giữ lại bởi các phần khác của mã của bạn, thời gian duy nhất tôi trả về byte thô trong mã của tôi là nếu tôi biết nó sẽ có sẵn cho cuộc đời của đối tượng trả về, theo cách đó nếu tôi cần phải giữ dữ liệu tôi có thể giữ lại lớp chủ sở hữu.

Apple thường sẽ sử dụng mô hình

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

và sau đó ghi lại rằng nếu bạn cần các byte ngoài chu kỳ autorelease hồ bơi hiện nay thì bạn sẽ phải sao chép nó.

+0

Nhưng đó không phải là cùng một vấn đề, chỉ cần bây giờ với một đối tượng thay vì một con trỏ nguyên? Đối tượng phải được giải phóng, con trỏ thô phải được giải phóng. Trong cả hai trường hợp, thiết kế nên được như vậy mà nó là khá rõ ràng khi họ có thể được loại bỏ. –

+0

Nó dễ dàng hơn để đối phó với một đối tượng bởi vì bạn có thể sau đó dính vào các quy tắc giữ lại/phát hành.Nếu bạn trả về byte thô từ một phương thức, làm thế nào để bạn biết người gọi của phương thức quản lý bộ nhớ một cách chính xác, điều gì sẽ xảy ra nếu người gọi phương thức không quan tâm đến các byte được trả về. Nếu các byte được trả về từ một phương thức riêng thì bạn có thể làm những gì bạn thích, nhưng nếu nó là một phần của giao diện công cộng thì hãy làm bằng chứng ngu ngốc để bạn không phải nhớ phương pháp mà bạn đã viết cách đây 6 tháng cư xử theo cách thông thường, nó đơn giản hơn nhiều để dính vào một tập hợp các quy tắc đơn giản. –

+0

Đó là lý do tại sao tôi sẽ không ** trả lại ** bộ nhớ. Tôi sẽ nói với người gọi rằng nó phải lớn đến mức nào và sau đó người gọi có thể vượt qua một bộ đệm mà họ đã cấp cho bạn. Bạn chỉ cần điền vào bộ đệm. Bằng cách đó, quyền sở hữu rõ ràng hơn nhiều, IMO. –