Question

I get this error on an NSMutableArray:

  -[Not A Type release]: message sent to deallocated instance 0x1006e29c0

It happens on this line:

     [_array removeAllObjects];

Now, I understand what the error means but not why it happens in this case.

I've added an NSLog right before the above line like so:

      NSLog(@"%@", [_array class]);

And this executes normally and with the correct behavior, this is the log:

 2013-03-13 11:19:27.366 App[66921:303] __NSArrayM
 2013-03-13 11:19:27.367 App[66921:303] *** -[Not A Type release]: message sent to deallocated instance 0x1006e29c0

So right before removing it doesn't seem to be deallocated..

Even if I remove the removeAllObjects call and replace it with the below line, I still get the same error.

     _array = [[NSMutableArray alloc] init];

All I'm doing elsewhere in the code is calling [_array addObject:...]

_array is a strong property:

@property (strong) NSMutableArray *array;

The array is first initialized in the init method.

EDIT: I'm adding AXUIElementRefs to this array like so:

 [_array addObject:(__bridge_transfer id)elementRef];

I thought the __bridge_transfer brings it over to ARC and I wouldn't need to manage any of that?

What could be the problem?

UPDATE: Here is a sample project: http://users.telenet.be/prullen/AXMemory.zip

This is a working project as I'm using __bridge and not __bridge_transfer.

This project contains a simple loop that does the same thing over and over again. This is to demonstrate that with just __bridge, the AXUIElementRefs never get released. They stay in memory. That's what I see in the Instruments profiler too. You can also see the memory usage increasing every few seconds via activity monitor.

The AXUIElementRefs were obtained via AXUIElementCopyMultipleAttributeValues - so I would assume that I would have ownership of them? Nevertheless, changing to __bridge_transfer results in the errors above.

If anyone could take a look at this and let me know what I'm doing wrong, that would be much appreciated.

I get an array of properties via the following statement: (line 60).

         AXUIElementCopyMultipleAttributeValues(frontWindowRef, attributes,0,&attributeValues);

Line 110 I assign the AXUIElement (looping over the children array):

             element = CFArrayGetValueAtIndex(childrenArrayRef, i);

Line 112 is where I add the AXUIElementRef to the array:

             [_array addObject:(__bridge id)(element)];

Line 36 is where I empty it if it's over 500 elements:

if ([_array count] > 500) {
    [_array removeAllObjects];
}
Was it helpful?

Solution

You can't just assume that __bridge_transfer "brings it over to ARC and [you] wouldn't need to manage any of that". You have to understand what rights and responsibilities you had for elementRef at the time (which we can't tell from what you've written).

I find it's much easier to understand the bridge casts if you use the corresponding CFBridgingRetain() and CFBridgingRelease() functions. __bridge_transfer is the same as CFBridgingRelease(). So, the question is: do you own elementRef at the time? Is it appropriate for you to release it?

Consider, would the following have been correct?

[_array addObject:(__bridge id)elementRef];
CFRelease(elementRef);

If not, then neither is __bridge_transfer.

From the nature of the error you're getting, I strongly suspect you were not entitled to release elementRef, so you were not entitled to tell ARC that it owns it and must release it. You have caused the AXUIElementRef to be over-released. You should just have used a __bridge cast – no "transfer" and no CF…Release().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top