0

I am writing a custom assertion macro, when assertion failed, this function is called

void _XLCAssertionFailedCritical(NSString *format, ...)
{
    va_list ap;
    va_start(ap, format);

    // this suppose to throw exception
    [NSException raise:NSInternalInconsistencyException format:format arguments:ap];

    va_end(ap); // <---- this line is unreachable? 
}

But I then realized that this function have a memory leak... va_end(ap); is unreachable.

I can use other method to create and throw exception, but this method is just bugging me. It seems not possible to use it without memory leak?

I understand that exception is not something suppose to happen in normal control flow, but I still want to write memory-leak-free problem even under exceptional cases.

This method mean to be a convenient method so raise an exception with some format string can be simpler. But with the cost of a memory leak?

Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
  • The problem is not tied to `+[NSException raise:format:arguments:]`. It always applies when working with variable argument lists. It's part of the general problem that exception safety and generic C code do not go well together. In this case the best solution is to circumvent throwing through the `va_start` - `va_end` interval. – Nikolai Ruhe Aug 07 '14 at 12:32

1 Answers1

0

I'm not certain if that will cause a leak, especially as it's fatal if it's an assertion, but it doesn't look very nice does it. I would suggest formatting the string and then passing that straight to [NSException raise:format:]

void _XLCAssertionFailedCritical(NSString *format, ...)
{
    va_list ap;
    va_start(ap, format);
    NSString *message = [[NSString alloc] initWithFormat:format
                                               arguments:ap];
    va_end(ap);

    [NSException raise:NSInternalInconsistencyException
                format:@"%@", message];
}
Droppy
  • 9,691
  • 1
  • 20
  • 27