0

我正在将图像数据从文件转码为 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);
4

2 回答 2

5

这里有几个问题:

// 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,这可能是导致您崩溃的原因。

// 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并在释放它时尝试释放它。由于您已经释放了它,因此该操作将以不可预知的讨厌方式失败。


我们如何解决这个问题?尝试这样的事情:

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];

该方法的其余部分应该是相同的,只是您不再有要释放的缓冲区(实际上您之前真的没有)。

于 2010-10-04T09:07:51.517 回答
3
NSData *dataToEncode = [NSData dataWithBytesNoCopy:base64buffer length:sizeof(base64buffer) freeWhenDone:YES];

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

于 2010-10-04T10:42:53.290 回答