2016-12-29 8 views
1

にNULLになるのはなぜ私がバックグラウンドスレッドで動作するC++書かれたライブラリからいくつかのイベントがあります。いつか変数はブロック

virtual void OnData(const char* data) 
{ 
    NSLog(@"Here 'data' string is present %s", data); 
    @autoreleasepool { 
     NSString* sData= [NSString stringWithCString:data encoding:NSUTF8StringEncoding]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSLog(@"Here _sometimes_ 'data'(%s) is nil (\0). But sData is always present %@", data, sData); 
      [callback OnData:sData]; 
     }); 
    }; 
} 

そしてを時々私は、引数にdispatch_asyncブロックにNULL(私は実際にそのゴミを疑う)持っています変数。しかし、ローカルNSString変数は常にここにあります。どうして?

P.S.この状況で実際に@autoreleasepoolを使用する必要がありますか?

+2

これはC++ではありません。 – Barmar

+0

Objective-CとC++が混在 – BugaBuga

答えて

3

asyncブロックが実行されるまでにconst char *dataが指していたバッファの寿命については保証がありません。 dataは、その時点でポインタをぶら下げている可能性があります(そのように仮定してください)。 Cスタイルのポインタは、非同期参照やそれらが最初に作成したコンテキスト外で使用するのは非常に危険です。

、あなたはメモリ管理対象オブジェクト(例えばNSDataNSStringなど)を使用する必要がありますいずれか、または、あなたはCスタイルのポインタを使用して主張し、非同期ブロックでこのポインタを参照する必要がある場合は、あなた自身のバッファにデータをコピーしますそのバッファを使用して、非同期ルーチンでそのバッファを使用し終わったら解放してください。この場合、sDataがあるので、その後はdataを参照しないでください。


P.S.この状況で@autoreleasepoolを使用する必要があるかどうか後で尋ねます。

要するに、ほとんどの場合、追加の自動解放プールは必要ありません。特に、Grand Central Dispatch(例:dispatch_async)を使用している場合、独自の自動解放プールがあるため、作成する必要はありません。そして、あなたのメインスレッドが実行ループに戻ってくると、再びプールが排水されます。手短に言えば、独自のNSThreadオブジェクトをインスタンス化するときは、手動で作成した自動解放プールだけが必要です。

実行ループに戻す前にメモリを大量に消費すると、自動解放プールが導入されることがあります。その場合、アプリケーションのピークメモリ使用量を減らすために自動解放プールを追加します。しかし、これはそのようなケースの1つではないようです。

1

あなたはこのような何かがあった場合:

void CallOnData() 
{ 
    char *test = malloc(5 * sizeof(char)); 
    strcpy(test, "test"); 
    OnData(test); 
    free(test); 
} 

をあなたは、データがブロック内の「NULL」であることを期待すべきです。

あなたがARCを使用していると仮定して、自動解放は必要ありません。

+0

なぜ 'autoreleasepool'が必要ではないのですか? 'autoreleasepool'なしで作成された新しいスレッドから呼び出されます。 – BugaBuga

+1

この回答は、OSX 10.9、iOS 7、およびそれ以降について、NSThreadとautoreleasepoolに関するいくつかの点を明らかにしています。 http://stackoverflow.com/a/30519746/16524 – Fostah

関連する問題