views:

55

answers:

2

I have the following method:

(void)makeString:(NSString *)str1,... {

   va_list strings;

   NSString *innerText = [[NSString alloc] init];
   NSString *tmpStr = [[NSString alloc] init];

   if (str1) {

       va_start(strings, str1); 

       while (tmpStr = va_arg(strings, id)) { 
            innerText = [innerText stringByAppendingString:tmpStr];
       }

       label.text = [str1 stringByAppendingString:innerText];
   }

   [tmpStr release];

}

I will eventually get to Objective C Memory Management reading, where I'm sure I will find the answer to this - probably related to pointers and copying - , but for now, can anyone explain why if I add [innerText release]; as the last line of this function, i get an EXC_BAD_ACCESS error at runtime?

A: 

stringByAppendingString returns an autoreleased string, which is replacing your original assignment. So your release is not needed. But you are leaking memory with the two allocs above.

You should probably use [NSString initWithCString:va_arg(strings, id)] to assign the tmpStr too.

Sophtware
thanks! removed the allocs - couldn't get the while (tmpStr = [NSString initWithCString:va_arg(strings, id)]) {}to work.
R.J.
Of course you couldn't. `initWithCString:` wants a `char *` and not an `id`. See my answer.
Tilo Prütz
@Sophtware: I think your answer could be more helpful. The release is not “not needed” but wrong as soon as `str1` is not nil. Also `[NSString initWithCString:va_arg(strings, id)]` cannot work. As I explained in my previous comment.
Tilo Prütz
A: 

First, your code is erroneous.
As far as I can see you are only concatenating the strings to assign the result to label.text.
I assume that label is an ivar, so label.text = … ist legal. Then the following should do it:

- (void)makeString: (NSString *)str1, ...
{
   if (str1) {
       NSString *tmpStr;

       va_list strings;
       va_start(strings, str1);
       while (tmpStr = va_arg(strings, id)) {
            str1 = [str1 stringByAppendingString: tmpStr];
       }

       label.text = [str1 retain];
   }
}

Some notes:

  • You should not release any input parameter unless your method is about releasing something.
  • As the first answer stated, you should not release the result of stringByAppendingString: unless you have retained it before.
  • You should retain the object assigned to label.text because you obviously want to use it. You should release it if you do not need it anymore.
Tilo Prütz