繁体   English   中英

来自NSInputStream的NSData dataWithBytesNoCopy

[英]NSData dataWithBytesNoCopy from NSInputStream

我正在将图像数据从文件转码为base64编码的字符串,然后在使用NSStream读取文件时又转回字节。 我想我快要到了,但是在转换过程中,我经常在不同地方遇到EXC_BAD_ACCESS。

我对NSStream和缓冲区世界还很陌生,所以如果我在这里采用绝对错误的方法,请随时告诉我。

到目前为止,这是我得到的:

// Copy the bytes from our file input stream buffer
void *base64buffer = malloc(self.buffer[self.bufferOffset]);

// Convert the bytes to NSData for the base64 encode
NSData *dataToEncode = [NSData dataWithBytesNoCopy:base64buffer length:sizeof(base64buffer) freeWhenDone:YES];

// Convert our NSData into a base64 encoded string
NSString *base64EncodedData = [dataToEncode base64EncodedString];

// Convert our base64 encoded string back into NSData
NSData *encodedData = [base64EncodedData dataUsingEncoding:NSUTF8StringEncoding];

// Write the bytes to our output stream
bytesWritten = [self.producerStream write:[encodedData bytes] maxLength:[encodedData length]];

// Clean up
dataToEncode = nil;
base64EncodedData = nil;
encodedData = nil;
free(base64buffer);

这里有几个问题:

// Copy the bytes from our file input stream buffer
void *base64buffer = malloc(self.buffer[self.bufferOffset]);

这并没有按照您的评论所说的做。 您刚刚完成的操作在self.buffer[self.bufferOffset]处分配了与size_t相同大小的缓冲区(4字节或8字节无符号整数),基本上,您尝试分配实质上是随机大小的缓冲区。 如果大小太大,则会返回NULL,这可能是导致崩溃的原因。

// Convert the bytes to NSData for the base64 encode
NSData *dataToEncode = [NSData dataWithBytesNoCopy:base64buffer length:sizeof(base64buffer) freeWhenDone:YES];

这并没有按照您的想法做。 sizeof(base64buffer)是4还是8,具体取决于您是以32位还是64位模式进行编译。 它是指针的大小,而不是缓冲区的大小。

free(base64buffer);

创建初始NSData时,对“ freeWhenDone”说“是”。 这意味着NSData拥有base64buffer所有权, base64buffer在释放后尝试释放它。 由于您已经释放了它,因此该操作将以无法预测的讨厌方式失败。


我们该如何解决? 尝试这样的事情:

size_t bufferLengthInBytes = .... // you'll need to figure out how to get this

// Next, instead of mallocing my own buffer for the data, I'll let the runtime do it for me.
// I'm assuming that self.buffer is a pointer to the bytes you want to copy.
NSData* dataToEncode = [NSData dataWithBytes: self.buffer length:bufferLengthInBytes];

// I'm not sure where the method base64EncodedString comes from.  I assume you have a category to do this.
NSString *base64EncodedString = [dataToEncode base64EncodedString];

该方法的其余部分应该相同,除了您没有缓冲区可以释放为止(事实上,您实际上没有使用过)。

NSData *dataToEncode = [NSData dataWithBytesNoCopy:base64buffer length:sizeof(base64buffer) freeWhenDone:YES];

释放dataToEncode时,此行将执行free(base64buffer),因为freeWhenDone: YES 因此,您将释放相同的内存空间两次。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM