4

理解できない問題が発生しています。たくさんの検索を行い、約50の異なるバリエーションを試しましたが、これまでのところサイコロはありません。これが私のジレンマです。

私には3つの方法があります。1つはPageViewオブジェクトが読み込まれるときに呼び出され、もう1つはユーザーが変更を加えるたびに呼び出され、最後はユーザーがページを離れるたびに呼び出されます。

最初の方法:

- (void)captureInitialLinesTexture {
@autoreleasepool {
    self.initialLinesTextureCaptured = TRUE;
    GLubyte *buffer =(GLubyte *) malloc (1024 * 1024 * 4 * sizeof(GLubyte));
    glPixelStorei(GL_PACK_ALIGNMENT,1) ;
    glReadPixels(0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    glBindTexture(GL_TEXTURE_2D, [pageTexture name]);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    NSData __autoreleasing  *tempData = [NSData dataWithBytes:buffer length:1024*1024*4*sizeof(GLubyte)];
    if (textureData == nil) {
        textureData = [self.pageController.notebookDoc newTextureInPage:self.page];
    }

    [pageTextures addObject:tempData];
    if ([pageTextures count] > 5) {
        [pageTextures removeObjectAtIndex:0];
    }
    textureData.textureData = tempData;
    textureData.page = self.page;
    self.page.texture = textureData;
    self.page.lastLineId = [NSNumber numberWithInt:self.pageController.newLineId - 1];
    [self.pageController saveNotebookWithUndo:FALSE];
    free((GLubyte*)buffer);
  }
}

2番目の方法:

-(void)capturePageTexture {
@autoreleasepool {
    GLubyte *buffer =(GLubyte *) malloc (1024 * 1024 * 4 * sizeof(GLubyte));
    glPixelStorei(GL_PACK_ALIGNMENT,1) ;
    glReadPixels(0, 0, 1024, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    NSData __autoreleasing  *tempData = [NSData dataWithBytes:buffer length:1024*1024*4*sizeof(GLubyte)];
    [pageTextures addObject:tempData];
    if ([pageTextures count] > 5) {
        [pageTextures removeObjectAtIndex:0];
    }
    free((GLubyte*)buffer);
  }
}

そして最後の方法:

-(void)attemptInstantPageTextureCapture {
  if ([pageTextures count] > 0) {
      self.page.texture.textureData = [pageTextures lastObject];
      self.page.lastLineId = [NSNumber numberWithInt:self.pageController.newLineId - 1];
      [self.pageController saveNotebookWithUndo:FALSE];
  }
  [pageTextures removeAllObjects];
  pageTextures = [NSMutableArray arrayWithCapacity:0];
}

私の問題は、これらのNSData*tempData変数にあります。何らかの理由で、私のPageViewが消えた後(Allocations Instrumentsで発見された)、そのうちの1つがランダムにぶらぶらしています。

PageViewをロードすると、captureInitialLinesTextureが起動します。次に、多くのペンストロークを追加し、ストロークごとにcapturePageTextureを起動して、NSMutableArray名pageTexturesに最大5つのNSData変数を保持できます。PageViewを離れると、NSMutableArrayが空になります。

さて、ここで壁にぶつかります。NSDataの割り当ては常に同じサイズで、この場合は4MBです。ページが読み込まれると、1つの4MBが割り当てられます。ペンストロークを行うと、さらに最大5つまで取得できます。次に、PageViewを離れると、4 MBの割り当て(NSData)のうち最大5つが解放されますが、常に1が残ります。次に、機器のCall Treeに移動すると、最初のメソッドまたは2番目のメソッドからランダムに通知されます。方法。配列に格納されている5つのNSDataをダンプしても問題がないのに、何らかの理由で1つのNSDataがどこかに残っているのはなぜですか。さらに、この謎のNSDataは、どちらの方法からもランダムに発生します。

私が言ったように、私は検索して検索しましたが、この問題の解決策を見つけることができません。4MBのメモリは明らかに巨大であるため、この種のリークが発生すると、時間の経過とともにアプリが強制終了されます。

1回の試行からの割り当て: 1回の試行からの割り当て

その試みのためにツリーを呼び出します: その試みのためにツリーを呼び出す

別の試みのための割り当て: 別の試みのための割り当て

他の試みのためにツリーを呼び出します: 他の試みのためにツリーを呼び出す

同じ正確なコードが毎回起動し、ランダムになるたびにNSDataが存続します。誰かが私が間違っていることを知っていますか?「page」変数と「textureData」変数は、疑問に思われる場合に備えてNSManagedObjectsです。私が試したことに関しては:

NSDataオブジェクトに割り当ててから、initWithBytes:lengthを呼び出します。

initWithBytesNoCopy:Length:-free((GLubyte *)buffer);を呼び出さなかった

initWithBytesNoCopy:Length:freeWhenDone:-free((GLubyte *)buffer);を呼び出さなかった

上記の2つの試行のNSDataクラスメソッドバージョン

@autoreleasepoolを使用していません

var宣言に__autoreleasingを使用しない

NSMutableArraypageTexturesをPageViewのプロパティにする

NavigationControllerスタックからポップされる前にPageViewをnilに設定する

__strongを使用してpageTextures可変配列を反復処理し、すべてのNSDataをnilまたはnullに設定します。

上記のように、これはすべて、ナビゲーションコントローラーにプッシュされてからポップされるPageViewController内の多くの種類の1つであるPageViewクラスで行われます。PageViewController(PageViewの唯一のスーパービュー)がナビゲーションスタックからポップされると、1つのランダムなNSData割り当てがまだ有効です。

どんな提案でも非常にありがたいです!上記のコアデータ要素に関する限り、コードは計画どおりに機能します。唯一の問題は、卑劣なライブNSData割り当てです... :(

4

3 に答える 3

4

しばらく前に問題を解決しましたが、他の誰かが同じ問題を抱えている場合に何が起こったのかを投稿すると考えました. 基本的に問題は、コア データ エンティティに割り当てられている NSData オブジェクトと、コア データが自身のメモリを解放するタイミングを制御していることです。したがって、コードは健全に見えますが、NSData オブジェクトが範囲外になり、実行ループが終了した後 (ARC が正常に開始されたとき) に、コア データがまだ NSData オブジェクトを保持していました。

この問題を回避するために、NSData をファイルに保存し、コア データ エンティティにブール データ (NSData) ではなくファイル パスの文字列 (NSString) のみが含まれるようにモデルを変更しました。

問題が解決しました :)

于 2012-05-31T14:50:33.837 に答える
0

__autoreleasingキーワードは、あなたが思っていることをしません。これは、初期化されていないポインタを含むポインタを、それらを初期化するメソッドに渡すために使用されます。メソッドは、呼び出し元のメソッドで使用されるように戻ることを唯一の目的としているため、初期化した値を保持しないことを認識します。このコンテキストでは必要ありません(デフォルトのstrongは問題ありませんが、スコープ外になると解放されます)。そのキーワードを削除したときのエラーはまったく同じですか?

于 2012-05-15T01:05:16.467 に答える