2011-08-09 31 views
1

FIXED:我不確定爲什麼。代碼已經在下面更新,並且在底部註釋CGImage/UIImage傳遞導致EXE-BAD-ACCESS

我有一個非常奇怪的錯誤,在模擬器上不顯示(即使運行樂器時),除非我打開所有的殭屍和調試選項。但是,一分鐘更新後(每秒更新1次)它會使手機崩潰。我有一個二維數組,我採取了一個子集,應用一個色彩映射,並轉變成一個圖像(這個數組不斷變化)。然後,我將該圖像傳遞給模型,並且一旦它接收到更新通知,viewcontroller就從模型中抓取它。我將佈局3類-Spectrogram,模型,視圖控制器:

下面是每個重要位(還有更多,但不相關):

Spectrogram.h(對不起,我不能讓這個正確縮進放在這裏)

@interface: Spectrogram : NSObject 
{ 
    NSMutableData *arrayData; 
} 
//renamed so Xcode allows the object with +1 reference count to be returned 
- (CGImageRef)newSpectrogramImage; 

Spectrogram.m

@implementation Spectrogram 
- (CGImageRef)newSpectrogramImage 
{ 
    //slightly reordered 
    NSMutableData *imageData = [[NSMutableData alloc] init]; 
    ...code to go through arrayData and colormap it (get RGB transform) and store in imageData... 
    CGImageRef arrayImage = nil; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    //specifically tell CGImage there is no alpha channel 
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNone; 
    //Use the toll-free bridge between NSData and CFData 
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)imageData); 
    arrayImage = CGImageCreate((slices-startSlice), bins, 8, 24, 3*(slices-startSlice), colorSpace, bitmapInfo, provider, NULL, false, kCGRenderingIntentDefault); //image is rotated now, so width and height are switched 
    CGColorSpaceRelease(colorSpace); 
    CGDataProviderRelease(provider); 
    CGImageRelease(arrayImage); 
    [imageData release]; 
    //Pass the CGImageRef with a reference count of 1 
    return arrayImage; 
} 

Model.h

@interface: Model : NSManagedObject 
{ 
    Spectrogram *spectrogram; 
} 
//Function the viewController can call to get the update 
- (CGImageRef)newSpectrogramImage; 

Model.m

@implementation Model 
... there is a function that adds new data to the array and notifies all listeners... 
- (CGImageRef)newSpectrogramImage { 
    return [spectrogram newSpectrogramImage]; 
} 

ViewController.h

@interface: ViewController : UIViewController 
{ 
} 
//the root controller actually alloc's the record, and sets this property when creating this view 
@property (nonatomic, retain) Record *currentRecord; 

ViewController.m

@implementation ViewController 
@synthesize spectrogramView; 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [[NSNotificationCenter ... listen for model updates... 
} 

//now, the real meat 
- (void)recordUpdated:(NSNotification*)notification 
{ 
    CALayer *myLayer = self.view.layer; 
    CGImageRef spectrogramImage = nil; 
    spectrogramImage = [currentRecord newSpectrogramImage]; 
    myLayer.contents = (id)spectrogramImage; 
    CGImageRelease(spectrogramImage); 
} 

我在最後一天改變了這個這麼多次試圖追捕何處以及爲何失敗。我嘗試過傳遞CGImageRef(但因爲這不是一個對象,所以我很擔心複製什麼可以是一個巨大的圖像),但它仍然失敗。它在模擬器中完美運行(將運行數十分鐘)。但在iphone上一分鐘內失敗,或者如果我打開模擬器的調試選項(一旦加載viewcontroller,它將會失敗)。

在附註中,這可能有些用處。這個視圖控制器作爲模式視圖加載時,手機側轉(偉大的工程)。但是,我在那裏有很多NSLogs,我發現這個viewcontroller的dealloc在mainviewcontroller甚至被viewwilldisappear之前調用 - 但它仍然運行。然後當手機返回並且視圖消失時,再次調用該控制器的dealloc。

注意 在模擬器中運行良好的版本將CGImageRefs一直傳遞給viewController而不是UIImages。我已經嘗試了至少50個不同的CGImage中創建UIImage的組合,上面列出的僅僅是其中的一個(它們都最終失敗,或者立即失敗)。值得注意的是,與上面的代碼,如果我這樣做添加到ViewController modelUpdated:

CGSize size = currentModel.spectrogramImage.size; 
NSLog(@"width: %f", size.width); 

,並註釋掉它分配給spectrogramView,寬度正確地報告,所以UIImage的是越來越傳承下去,這只是沒有得到保留(這是我的理解EXE_BAD_ACCESS錯誤)。

另外,最近我收到關於

self.spectrogramImage = [spectrogram getSpectrogramImage]; 

線丹EXE_BAD_ACCESS。所以,我認爲這個錯誤可能在頻譜圖類中。即使CGImage和UIImage代碼是從蘋果公司的例子中獲得的。

固定音符 我讀了設置的CALayer的內容是第一個通過CGImageRef到視圖快得多的方式 - 沒有UIImage的中介。不幸的是,我只做了一些改變,所以我看不到每一次迭代。但是,我知道我有幾次非常類似這樣的事情,並且一直在崩潰。現在的問題是,當前編寫的程序會因EXE_BAD_ACCESS而崩潰。如果我提高引用計數(或者沒有釋放它),那麼它可以很好地工作,但對象會泄漏。我仍然不明白這是如何可能的。爲了使泄漏和BAD ACCESS之間的差異爲1(而不是2或更多)的引用計數。

+0

在哪條線上發生錯誤訪問? – sergio

+0

它只發生,如果我有self.spectrogramView.image =行在那裏。如果我發表評論,該視圖是無用的,但它不會崩潰(即使模型仍然將圖像保存到它自己的ivar中)。即使我將傳遞的對象從UIImage *切換到CGImageRef,這也是如此。 –

+0

好的,所以我認爲你應該在你的代碼後面發佈:alloc/init'spectrogramView',以及你用這個對象做的任何事情; alloc/init'currentModel',以及你用這個對象做的任何事情...... – sergio

回答

1

我無法回答你的具體問題,但這可能會幫助你知道發生了什麼好一點。我有一個函數「logMemUsage」,用於輸出內存使用情況,並顯示自上次以來更改的內容。如果您每秒鐘撥打一次,您可以更好地瞭解內存在您的應用中的使用方式。如果它不斷增長,那麼顯然存在一個泄漏,如果它按照你期望的那樣升降,這很好,如果它在你認爲應該的時候沒有下降,你會看到它的。它位於Utilities.h/.m中的github here

+0

我觀察過儀器中的內存使用情況,它按預期增長(〜1MB /小時)。數組(有3個)不斷被添加到接收的數據 - 這是設計的一部分,這是一個分析應用程序。當前的記錄關閉後,我會進行一些清理以壓縮核心數據存儲的數據,並且當記錄被檢查時,我解壓縮或重新創建導出的數據(如譜圖陣列和圖像)。儀器也說沒有物體在泄漏。我讀過Quartz2D在內存方面可能會有問題。 –

1

很難從您發佈的內容中弄清楚這一點,但爲什麼不在所有分配的數據上使用保留屬性?例如,您從getSpectrogramImage返回一個自動釋放的UIImage,並通過調用self.spectrogramImage = [spectrogram getSpectrogramImage];將其存儲到Model中;但是,我不能在任何地方看到spectrogramImage的屬性,重新使用自我。機制。僅僅是你不打算髮布它?它被寫入的方式可能會被自動釋放,然後當您嘗試使用它時...

+0

+1,'Model'中的'spectrogramImage'需要'@property(retain)'。 – darvids0n

+0

對不起,model.h被寫入不正確(這是我爲剪切和粘貼以及從內存中做一些事情而得到的),spectrogramImage被保留。 –

相關問題