防止从 C++ 代码调用的 Objective-C 对象被释放
Prevent Objective-C object called from C++ code being released
这是我的情况:
我正在使用音频队列服务来录制声音。当调用回调函数时(一旦缓冲区已满),我将缓冲区内容发送到一个 objective-C 对象来处理它。
void AQRecorder::MyInputBufferHandler(void * inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp * inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription* inPacketDesc)
{
AQRecorder *aqr = (AQRecorder *)inUserData;
try {
if (inNumPackets > 0) {
NSLog(@"Callback ! Sending buffer content ...");
aqr->objectiveC_Call([NSData dataWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataBytesCapacity]);
aqr->mRecordPacket += inNumPackets;
}
if (aqr->IsRunning())
XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL), "AudioQueueEnqueueBuffer failed");
} catch (CAXException e) {
char buf[256];
fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
}
}
void AQRecorder::objectiveC_Call(NSData *buffer) {
MyObjCObject *myObj = [[MyObjCObject alloc] init];
[myObj process:buffer];
}
这里的问题是我在处理过程中得到了一个 EXC_BAD_ACCESS(来自 myObj 的处理方法),经过一些研究我猜它与myObj 正在发布。
MyObjCObject.process 从缓冲区内容执行 for 循环,即使我只是对缓冲区值执行 NSLog,我也会收到 EXC_BAD_ACCESS 错误。
-(void)run:(NSData *)bufferReceived {
NSUInteger bufferSize = [bufferReceived length];
self.buffer = (short *)malloc(bufferSize);
memcpy(self.buffer, [bufferReceived bytes], bufferSize);
for(int i= 0; i < bufferSize; i++) {
NSLog("value: %i", buffer[i]);
}
}
你能告诉我怎么做吗?
ps:我的文件有 .mm 扩展名,在整个项目上启用了 ARC,我的其余代码似乎按预期工作。
谢谢!
您 malloc 缓冲区并转换为“(short*)”,但随后您使用 'bufferSize'(字节数)枚举缓冲区。这意味着 'for' 循环最终会尝试读取缓冲区末尾,可能导致 'EXE_BAD_ACCESS'。那是因为每次迭代都向前移动 'short' 而不是 'byte'。您应该将循环更改为:
for(int i= 0; i < bufferSize / sizeof(short); i++) {
NSLog("value: %i", buffer[i]);
}
或者改变 'buffer' 成员变量的类型。
这是我的情况:
我正在使用音频队列服务来录制声音。当调用回调函数时(一旦缓冲区已满),我将缓冲区内容发送到一个 objective-C 对象来处理它。
void AQRecorder::MyInputBufferHandler(void * inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp * inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription* inPacketDesc)
{
AQRecorder *aqr = (AQRecorder *)inUserData;
try {
if (inNumPackets > 0) {
NSLog(@"Callback ! Sending buffer content ...");
aqr->objectiveC_Call([NSData dataWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataBytesCapacity]);
aqr->mRecordPacket += inNumPackets;
}
if (aqr->IsRunning())
XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL), "AudioQueueEnqueueBuffer failed");
} catch (CAXException e) {
char buf[256];
fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
}
}
void AQRecorder::objectiveC_Call(NSData *buffer) {
MyObjCObject *myObj = [[MyObjCObject alloc] init];
[myObj process:buffer];
}
这里的问题是我在处理过程中得到了一个 EXC_BAD_ACCESS(来自 myObj 的处理方法),经过一些研究我猜它与myObj 正在发布。
MyObjCObject.process 从缓冲区内容执行 for 循环,即使我只是对缓冲区值执行 NSLog,我也会收到 EXC_BAD_ACCESS 错误。
-(void)run:(NSData *)bufferReceived {
NSUInteger bufferSize = [bufferReceived length];
self.buffer = (short *)malloc(bufferSize);
memcpy(self.buffer, [bufferReceived bytes], bufferSize);
for(int i= 0; i < bufferSize; i++) {
NSLog("value: %i", buffer[i]);
}
}
你能告诉我怎么做吗?
ps:我的文件有 .mm 扩展名,在整个项目上启用了 ARC,我的其余代码似乎按预期工作。
谢谢!
您 malloc 缓冲区并转换为“(short*)”,但随后您使用 'bufferSize'(字节数)枚举缓冲区。这意味着 'for' 循环最终会尝试读取缓冲区末尾,可能导致 'EXE_BAD_ACCESS'。那是因为每次迭代都向前移动 'short' 而不是 'byte'。您应该将循环更改为:
for(int i= 0; i < bufferSize / sizeof(short); i++) {
NSLog("value: %i", buffer[i]);
}
或者改变 'buffer' 成员变量的类型。