首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自NSInputStream的NSData dataWithBytesNoCopy

来自NSInputStream的NSData dataWithBytesNoCopy
EN

Stack Overflow用户
提问于 2010-10-04 13:01:10
回答 2查看 5.6K关注 0票数 0

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

我对NSStream和buffers的世界还很陌生,所以如果我在这里采用了完全错误的方法,请随时告诉我。

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

代码语言:javascript
复制
// 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);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-10-04 17:07:52

这里有几个问题:

代码语言:javascript
复制
// Copy the bytes from our file input stream buffer
void *base64buffer = malloc(self.buffer[self.bufferOffset]);

这并不像你的评论所说的那样。您刚才所做的是分配一个与size_t (4字节或8字节无符号整数)大小相同的缓冲区。在self.buffer[self.bufferOffset]中,基本上您尝试分配一个基本上是随机大小的缓冲区。如果大小太大,你会得到NULL返回值,这可能是导致崩溃的原因。

代码语言:javascript
复制
// 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位模式下编译。它是指针的大小,而不是缓冲区的大小。

代码语言:javascript
复制
free(base64buffer);

当您创建初始NSData时,您同意了"freeWhenDone“。这意味着NSData获得了base64buffer的所有权,并将在它被释放时尝试释放它。由于您已经释放了它,该操作将以不可预知的糟糕方式失败。

我们该如何解决这个问题呢?尝试如下所示:

代码语言:javascript
复制
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];

该方法的其余部分应该是相同的,除了你不再有一个缓冲区可供释放(事实上,你以前没有,真的)。

票数 5
EN

Stack Overflow用户

发布于 2010-10-04 18:42:53

代码语言:javascript
复制
NSData *dataToEncode = [NSData dataWithBytesNoCopy:base64buffer length:sizeof(base64buffer) freeWhenDone:YES];

当释放freeWhenDone:__YES.时,此行将执行dataToEncode释放(Base64buffer),因为因此,您将释放相同的内存空间两次。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3852946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档