我正在编写一个C ++程序,它有一个具有Objective-C ++实现的类。当有任何创建对象的机会时,每个函数都有一个自动释放池。
当多次调用特定对象函数时,我得到3条*** __NSAutoreleaseNoPool(): Object 0x10b730 of class NSCFArray autoreleased with no pool in place - just leaking
在此特定功能中有一个自动释放池,也可以在两个可以调用它的函数中。是否有可能我正在使用的框架之一是创建一些泄露的全局对象?
我尝试在__NSAutoreleaseNoPool
上设置一个断点,但它不会中断。我也设置了NSAutoreleaseHaltOnNoPool并且也无法打破。
编辑:这是代码,
qtdata.h:
#ifndef qtdata_h
#define qtdata_h
#include "../videodata.h"
class QTData : public VideoData
{
public:
QTData();
~QTData() { };
bool Open(const char *seqname, QImage *img = NULL);
bool ReadFirstFrame(const char *seqname, QImage &img);
private:
bool getFrame(void *handle, QImage *img);
};
#endif
qtdata.mm:
#include <CoreAudio/CoreAudio.h>
#include <QuickTime/Movies.h>
#import <QTKit/QTKit.h>
#include "qtdata.h"
QTData::QTData() : VideoData(){ };
// Open and read first frame into img
bool QTData::Open(const char *seqname, QImage *img)
{
NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
NSError *error;
QTMovie *movieHandle;
movieHandle = [[QTMovie movieWithFile:[NSString stringWithCString:seqname
encoding:NSUTF8StringEncoding] error:&error] retain];
if(movieHandle == nil)
{
[localpool release];
return(false);
}
[movieHandle gotoBeginning];
NSSize size = [[movieHandle attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
width = size.width;
height = size.height;
bool success = false;
if(img)
{
[movieHandle gotoBeginning];
success = getFrame(movieHandle, img);
}
[localpool drain];
return(success);
}
bool QTData::getFrame(void *handle, QImage *img)
{
bool success = false;
NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:QTMovieFrameImageTypeCVPixelBufferRef
forKey:QTMovieFrameImageType];
CVPixelBufferRef frame = (CVPixelBufferRef)[(QTMovie *)handle frameImageAtTime:[(QTMovie *)handle currentTime]
withAttributes:attributes error:nil];
CVPixelBufferLockBaseAddress(frame, 0);
QImage *buf;
int r, g, b;
char *pdata = (char *)CVPixelBufferGetBaseAddress(frame);
int stride = CVPixelBufferGetBytesPerRow(frame);
buf = new QImage(width, height, QImage::Format_RGB32);
for(int j = 0; j < height; j++)
{
for(int i = 0; i < width; i++)
{
r = *(pdata+(i*4)+1);
g = *(pdata+(i*4)+2);
b = *(pdata+(i*4)+3);
buf->setPixel(i, j, qRgb(r, g, b));
}
pdata += stride;
}
success = true;
*img = *buf;
delete buf;
CVPixelBufferUnlockBaseAddress(frame, 0);
CVBufferRelease(frame);
[localpool drain];
return(success);
}
bool QTData::ReadFirstFrame(const char *seqname, QImage &img)
{
NSAutoreleasePool *localpool = [[NSAutoreleasePool alloc] init];
NSError *error = nil;
QTMovie *movieHandle;
movieHandle = [[QTMovie movieWithFile:[NSString stringWithCString:seqname
encoding:NSUTF8StringEncoding] error:&error] retain];
if(movieHandle == nil)
{
[localpool drain];
return(false);
}
[movieHandle gotoBeginning];
bool success = getFrame(movieHandle, &img);
[localpool drain];
return(success);
}
答案 0 :(得分:2)
您必须为每个新线程创建自动释放池。检查main.m,它为主线程创建它。
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// your code
[pool drain];
注意:如果使用POSIX线程API创建辅助线程 而不是NSThread对象,你不能使用Cocoa,包括 NSAutoreleasePool,除非Cocoa处于多线程模式。可可 仅在分离其第一个NSThread后才进入多线程模式 宾语。要在辅助POSIX线程上使用Cocoa,您的应用程序必须 首先分离至少一个NSThread对象,它可以立即退出。 您可以使用NSThread测试Cocoa是否处于多线程模式 class方法isMultiThreaded。
所以你必须创建一个NSThread对象来启用Cocoa多线程模式。
NSThread *thread = [[NSThread alloc] init];
[thread start];
[thread release];
将所有obj-c代码包装在自动释放池中,如上面的代码。