NSData和嵌入式指针澄清

msk*_*skw 1 cocoa nsdata

有关Apple的文档NSData

NSData它的可变子类NSMutableData为字节缓冲区提供数据对象,面向对象的包装器.数据对象允许简单分配的缓冲区(即没有嵌入指针的数据)采用Foundation对象的行为.

"嵌入式指针"是什么意思?我的理解是,一旦你把字节放入其中,它就不知道它是什么,除非你在应用程序级解码它.谁知道他们在说什么?

Bri*_*man 5

NSData的目的是提供一种在不再需要时清理已分配数据缓冲区的方法,即当NSData的引用计数变为0时.在常见情况下,数据使用malloc分配,NSData使用相应的调用自由解除分配数据.这限制了字节数据的性质.它必须是普通旧数据.如果数据是一个包含字段的结构,该字段指向使用malloc(嵌入指针)分配的另一个内存区域,则嵌入式指针永远不会被NSData对象释放,从而导致内存泄漏.例如:

typedef struct Point {
    CGFloat x,
    CGFloat y
} Point;

typedef struct LineSegment {
    Point* start;
    Point* end;
} LineSegment;

// point does not contain any embedded pointers (i.e., it is Plain Old Data)
Point* point = malloc(sizeof(Point));
// pointData will call free on point to deallocate the memory allocated by malloc
NSData* pointData = [NSData dataWithBytesNoCopy:point length:sizeof(Point)];

Point* start = malloc(sizeof(Point));
Point* end = malloc(sizeof(Point));

// line contains two embedded pointers to start and end. Calling free on line
// without calling free on start and end will leak start and end 
LineSegment* line = malloc(sizeof(LineSegment));
line->start = start;
line->end = end;

// start and end will be leaked!
NSData* lineData = [NSData dataWithBytesNoCopy:&line length:sizeof(LineSegment)];

// Try this instead. Line is now Plain Old Data
typedef struct Line {
    Point start;
    Point end;
} Line;

// anotherLine does not contain any embedded pointers and can safely be used with
// NSData. A single call to free will deallocate all memory allocated for anotherLine
// with malloc
Line* anotherLine = malloc(sizeof(Line));

NSData* anotherLineData = [NSData dataWithBytesNoCopy:&anotherLine
                                               length:sizeof(Line)];
Run Code Online (Sandbox Code Playgroud)