ポインターを作成し、performSelectorInBackground:を使用して新しいスレッドに渡すObjective-Cメソッドがあります。問題は、スレッド内からそれに関連付けられたメモリを解放したいので、ポインタのアドレスをスレッドに渡す必要があることです。私が抱えている問題は、新しいスレッドが起動されると、呼び出し元のメソッドが終了し、ポインターがスコープ外になることです。スレッドがポインタのアドレスを受け取ることができる場所にそれを十分長く保つにはどうすればよいですか?
もちろん、メインスレッドで「pointerTest」メソッドを呼び出すだけで、これはすべて機能します。
これが私のコードです:
-(void)pointerTest:(NSValue*)pointer
{
void **p = (void**)[pointer pointerValue];
fprintf(stderr,"p was %s\n",(char*)(*p)); //prints "Hello There!"
free(*p);
*p = NULL;
}
さて、メインスレッドで:
-(IBAction)doTest:(id)sender
{
char *str = "Hello There!";
void *p = malloc(strlen(str)+1);
strcpy(p, str);
//this works
//[self pointerTest:[NSValue valueWithPointer:&p]];
//this fails
[self performSelectorInBackground:@selector(pointerTest:) withObject:[NSValue valueWithPointer:&p]];
if(!p){
fprintf(stderr,"p was NULL!\n");
}else{
fprintf(stderr,"p was NOT NULL: %s\n",p);
}
}
アップデート:
このコードは、pointerTest:にポインターを渡さないと、pointerTest:内からpを解放できないことを示しています。
-(void)pointerTest:(NSValue*)pointer
{
void *p = (void*)[pointer pointerValue];
fprintf(stderr,"p was %s\n",(char*)p); //prints "Hello There!"
free(p);
fprintf(stderr,"p was %s\n",(char*)p); //STILL prints "Hello There!"
*p = NULL;
fprintf(stderr,"p was %s\n",(char*)p); //prints "(null)"
}
さて、呼び出しメソッドで:
//I pass p, NOT a pointer to p
[self pointerTest:[NSValue valueWithPointer:p]];
if(p){
//p is not NULL, and in fact I can print its value
fprintf(stderr,"p was NOT NULL: %s\n",p);
}
ただし、pの代わりにpにポインターを渡すと、pointerTest内から期待どおりにその値を解放できます。pointerTestから戻ると、呼び出し元のメソッドでpがNULLになります。