Question

I'm intercepting CGEventRefs in two ways:

  • Returning value NULL to kill the event
  • Assigning the event a new CGEventRef via CGEventCreateKeyboardEvent()

Xcode's Analyzer tells me I have a potential leak when I create the new event. But I need to return that new event, so I can't CFRelease it there.

  • Is this Xcode error valid?

  • Where should I properly CFReleaseing the new CGEventRef that I create?

  • In both the null and new event cases, I don't know if I need to release the former value of the event.

  • Is appending "new" to the method name the correct way to fix this? I think it might be, for the case when I create a new event. But what of the other cases?

.

- (CGEventRef)modifySomeKeyboardEvents:(CGEventRef)event {

    CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
    NSLog(@"keycode: %d", keycode);

    switch (keycode) {
        case 0:
            NSLog(@"pressed 'a'");
            //Kill the event
            event = NULL;

            //Is a `CFRelease` of some kind needed here, to release the previous value?

            break;

        case 38:
            NSLog(@"pressed 'h'");

            //Send different character:
            CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
            CGEventRef newKeyEvent = CGEventCreateKeyboardEvent(eventSource, 1, true);
            CGEventSetIntegerValueField(newKeyEvent, kCGKeyboardEventKeycode, 51); // keycode '51' = backspace
            CFRelease(eventSource);

            event = newKeyEvent;

            //Can't CFRelease here, but somewhere?
            //CFRelease(newKeyEvent);

            break;

        default:
            break;
    }

    //Xcode error: "Potential leak of an object stored in newKeyEvent"
    return event;
}
Was it helpful?

Solution

The CGEventTapCallback documentation says

After the new event has been passed back to the event system, the new event will be released along with the original event.

Therefore you are not responsible for releasing the new event or the old event.

The analyzer doesn't know this, so you need to tell it. You can silence the analyzer by putting new at the beginning of the method name, but maybe it would be clearer to use copy, which also silences the warning:

- (CGEventRef)copyOrModifyKeyboardEvent:(CGEventRef)event {

(I guess newOrModifiedKeyboardEvent: would work just as well.)

I believe the analyzer ought to flag this too, since it now fails to return a +1 reference count when you just return the input event. But in my testing, it doesn't. The Xcode 4.6.2 analyzer gives me no warnings for this method:

- (CGEventRef)copyOrModifyEvent:(CGEventRef)event {
    CGEventRef newEvent;
    if (CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == 38) {
        newEvent = CGEventCreate(NULL);
    } else {
        newEvent = event;
    }
    return newEvent;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top