2

私は、テキストフィールドに関連付けられたこの些細なアクションメソッドを作成しました。
テキストフィールドにテキストを入力するたびに、PDFで検索が実行され、PDFView選択範囲まで自動的にスクロールします。

- (IBAction) search:(id)id
{
    NSString *query = [self.searchView stringValue]; // get from textfield
    selection = [document findString: query fromSelection:NULL withOptions:NSCaseInsensitiveSearch]; 
    if (selection != nil)
    {
        [self.pdfView setCurrentSelection:selection];
        [self.pdfView scrollSelectionToVisible:self.searchView];
    } 
}

問題は、3回または4回の検索の後EXC_BAD_ACCESS、行(i)に到達することです。
デバッグすると、クエリにがNSCFStringではなくが含まれていることがわかりますNSString
メモリ管理の問題だと思いますが、どこで?

ここに画像の説明を入力してください

些細なテストケース内で同じ問題を再現しました。

  @interface PDFRef_protoTests : SenTestCase {
   @private

      PDFDocument *document;

   }

  ........

 - (void)setUp
  {
     [super setUp];
     document = [[PDFDocument alloc] initWithURL: @"a local url ..."];
  }

- (void)test_exc_bad_access_in_pdfdocument
{
    for (int i =0 ;i<100; i++)
    {
        NSString *temp;
        if (i % 2 == 0) temp = @"home";
        else if (i % 3 ==0) temp = @"cocoa";
        else temp=@"apple";
        PDFSelection *selection = [document findString: temp 
                                   fromSelection:nil 
                                withOptions:NSCaseInsensitiveSearch]; 
        NSLog(@"Find=%@, iteration=%d", selection, i);
    }
}

更新

1)2回目の検索を実行するたびに、非同期検索(メソッドbeginFindString:withOptions)を使用した場合にも発生するようです。

2)MacRuby Issue Trackingで私のものと同様の問題を見つけました:http://www.macruby.org/trac/ticket/1029

3)一時的にガベージコレクションを無効にすると、動作するように見えますが、メモリが増加します。私は次のようなものを書きました:

[[NSGarbageCollector defaultCollector] disable];
[[NSGarbageCollector defaultCollector] enable];

周囲の検索コード

別の更新

非常に奇妙なことは、すべてが機能することもあるということです。私が掃除して再構築するよりも、問題が再び発生します。ある観点からは、100%再現性はありません。PDFKitまたは私がしなければならないいくつかのコンパイラ設定のバグが疑われます

再度更新する

親愛なる、それは非常にクレイジーに見えます。私は非常に些細で問題を簡単に再現するテストケースに集中したいと思います。どうしたの?このテストケースは、GCを(コードまたはプロジェクト設定によって)無効にした場合にのみ機能します

別の更新

バグのようですが、AppleのWebサイト( http://developer.apple.com/library/mac/#samplecode/PDFKitLinker2/Introduction/Intro.html#//apple_ref/doc/uid/DTS10003594)からPDFLinkerという例をダウンロードしました。)。この例では、PDFViewerを実装しています。私のアプリのコードとこの例は非常に似ています。同じPDFで同じ検索アクションを実行すると、メモリは300/400 MBで増加し、PDFLinkerは190MBで増加します。明らかに私のコードに何か問題があります。しかし、私はそれを少しずつ比較していて、メモリリークを挿入しているとは思いません(そしてInstrumentは私に証拠を与えません)。たぶん、プロジェクト全体の設定はありますか?

更新はまだ 64ビットから32ビットへの変更メモリ消費量が減少しました。確かに64ビットとPDFKitには問題があります。ところで、2回目の検索でもEXC_BAD_ACCESS

解決 策重要な点は、ガベージコレクションを含むPDFKitにバグがあることです。GCを無効にすると、すべて正しく機能します。分析を複雑にする別の問題がありました。プロジェクト設定でGCを無効にしましたが、ターゲット設定でGCを有効のままにしました。したがって、Appleの例のPDFLinked2は機能しましたが、私の例では機能しませんでした。

4

5 に答える 5

2

この種のことは通常、破壊されたオブジェクトへのポインタにぶら下がっている証拠です。ゾンビオブジェクト(を使用NSZombieEnabled)をオンにして、不良オブジェクトにアクセスしている場所とタイミングを正確に確認します。

于 2011-06-11T14:34:41.297 に答える
2

PDFKitにバグが見つかったことに同意します。

テストケースを実行すると、さまざまな形式のエラー(セグメンテーション違反、セレクターが理解されないなど)が発生しました。@ try / @ catchでコードをラップしても、このメソッドに関連するすべてのエラーを防ぐことはできません。

ログメッセージの印刷でもエラーが発生しました。

バグを回避するには、すでに発見したように、-findString:fromSelection:の呼び出し中にGCを無効にすることをお勧めします。

また、 GCを再度有効にする前に、選択から対象の値のコピーを必ず作成してください。選択範囲をコピーするだけではいけません。

コード内の複数の場所から検索を実行する場合は、別のメソッドを抽出して検索を実行することもお勧めします。次に、それを呼び出して、GCの無効化/有効化のネストを複製せずに検索を実行できます。

于 2011-06-17T05:46:16.807 に答える
1

スクリーンショットから判断すると、電源が入っているようには見えませんNSZombie。おそらくそれがあなたを助けない理由。オンにする方法は次のとおりです。

XcodeでNSZombieを有効にする方法は?

あなたが提供したスクリーンショットは他の点では非常に役に立ちましたが、あなたは本当にNSZombieこの種のエラーを理解する必要があります。まあ、それがあなたが投稿したコードからではないことが明らかでない限り。


編集:ガベージコレクションを使用しているというコメントを読みました。私はiOS開発者なので、Objective-Cでのガベージコレクションの経験は非常に限られていますが、私が理解している限りNSZombie、ガベージコレクション環境では機能しません。

ガベージコレクション環境でEXC_BAD_ACCESSを取得できるかどうかはわかりません。ただし、独自のポインターを作成し、オブジェクトを作成せずにそのポインターでメソッドを呼び出そうとすると、なぜそうするのかわかりません。

一部のフレームワークはガベージコレクションでうまく機能しないと聞きましたが、PDFKitがその中に含まれているとは思いません。とにかく、解決策はガベージコレクションを使用しないことかもしれません。おそらく、Appleにバグレポートを提出する必要があります。

于 2011-06-11T22:13:11.523 に答える
1

使用する前にsearchviewstringvalueオブジェクトを保持しようとしましたか?

高速入力時に発生し、非同期呼び出しで発生すると言うように、オブジェクトがポイントしている時間と、オブジェクトが検索で使用する時間stringValueの間に、オブジェクトがポイントしているオブジェクトが解放されている可能性があります。query

このようなことを試して、問題が解決するかどうかを確認できます。

- (IBAction) search:(id)id
{
    NSString *query = [[self.searchView stringValue] retain]; // get from textfield
    selection = [document findString: query fromSelection:NULL withOptions:NSCaseInsensitiveSearch]; 
    if (selection != nil)
    {
        [self.pdfView setCurrentSelection:selection];
        [self.pdfView scrollSelectionToVisible:self.searchView];
    } 

    [query release];

}

もちろん、解放される可能性もdocumentあります。どのように宣言しますか?それは保持のあるプロパティですか?お探しの時間までにリリースできますか?

編集:

2番目のパラメータをとしてコードを投稿したようですNULLが、スクリーンショットでは、この値はnilです。

ドキュメントにはNULL、検索を最初から開始する場合に使用する必要があると記載されています。

http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/QuartzFramework/Classes/PDFDocument_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003873-RH2-DontLinkElementID_1

そして、コンパイラーが解釈するように、そしてnil異なっNULLて、これ内部的にいくつかの奇妙な振る舞いを引き起こす可能性があります。

于 2011-06-15T00:46:43.407 に答える
1

メンバー変数として保持し、の代わりにPDFSelection *selection渡します。fromSelection:nil

パフォーマンスを向上させるためにPDFDocument、返されたインスタンスを保持することが可能です。PDFSelection

于 2011-06-15T10:20:10.487 に答える