I have an Objective-C method that creates a pointer, then passes it to a new thread using performSelectorInBackground:. The problem is, I need to pass the address of the pointer to the thread because I want to free the memory associated with it from within the thread. The problem I’m having is that when the new thread is launched, the calling method ends, causing the pointer to go out of scope. How do I keep it around long enough where the thread can receive the pointer’s address?
This all works of course if I simply call the “pointerTest” method on the main thread.
Here’s my code:
-(void)pointerTest:(NSValue*)pointer
{
void **p = (void**)[pointer pointerValue];
fprintf(stderr,"p was %s\n",(char*)(*p)); //prints "Hello There!"
free(*p);
*p = NULL;
}
Now, on the main thread:
-(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);
}
}
Update:
This code shows that if I don’t pass a pointer to pointerTest:, I cannot free p from within pointerTest:
-(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)"
}
Now, in the calling method:
//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);
}
However, if I pass a pointer to p instead of p, I can free its value as expected from within pointerTest: and upon returning from pointerTest, p is NULL in the calling method.
[I won’t ask why you’re mixing
malloca C-strings with Objective-C, I guess you’re experimenting. There is nothing wrong with doing so per se, it’s just unusual in a situation like this.]You don’t need to pass a pointer to a pointer at all.
A pointer is the name of a box. Some boxes contain characters, some employee records, etc. and some box names (of other boxes).
mallocfinds a box of the needed size and returns its name, you can pass that around just like you would pass an integer value – you don’t need to pass the name of the box containing the name of the box containing your characters…Also when you
mallocyou need to allow for the trailing NUL character on a C string, so add 1 to the string length.Try:
Note you don’t need to wrap
pup in anNSValueeither, nothing wrong with passing a pointer value to an Objective-C method.HTH
After Comments
You are confusing the validity of a pointer with what might happen to be in the memory the pointer refers to.
The memory referred to by your pointer is freed. Your pointer value is no longer valid after the call to
free– it is a dangling pointer.The memory referred to by your, now dangling, pointer value may be re-used at any time. It just happens that at the point of your
fprintfthe memory has not yet been re-used and so you see the old contents – freeing memory does not clear it out.Your store of
NULLinto the variable intends to remove your dangling pointer, doing so might be good practice in general but as you’ve found out taking the address of a short-lived variable and passing it to another method is a good way to create a dangling pointer. So you ended up trying to clean up a dangling pointer from box A to box B by using a dangling pointer to box A as box A had since been released itself… Let’s try that a explaining that a different way 😉In this case you created a pointer to the local variable (box)
pbelonging todoTest, as soon asdoTestcompletes the system returns the box that was being used forpto the free-box pile (or stack in this case) and your pointer became a dangling; when your original code forpointerTestthen tried to store aNULLinto that box via that, now dangling, pointer you hit a problem.