自动释放使用但仍然泄漏

时间:2012-01-18 22:46:35

标签: c++ objective-c

我正在编写一个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);
}

1 个答案:

答案 0 :(得分:2)

您必须为每个新线程创建自动释放池。检查main.m,它为主线程创建它。

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// your code
[pool drain];

阅读NSAutoreleasePool doc

  

注意:如果使用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代码包装在自动释放池中,如上面的代码。