我正在将图像数据从文件转码为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);
答案 0 :(得分:5)
这里有几个问题:
// 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
的所有权,并在解除分配时尝试释放它。由于你已经释放它,该操作将以不可预测的恶劣方式失败。
我们如何解决这个问题?尝试这样的事情:
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];
方法的其余部分应该是相同的,除非你没有可以释放的缓冲区(事实上你之前没有)。
答案 1 :(得分:3)
NSData *dataToEncode = [NSData dataWithBytesNoCopy:base64buffer length:sizeof(base64buffer) freeWhenDone:YES];
当dataToEncode解除分配时,此行将执行free(base64buffer),因为 freeWhenDone: YES 。因此,您将两次释放相同的内存空间。