简体   繁体   中英

Mac OS X, Objective-C crash with NSMutableArray

Environment: Mac OS 10.8.5, XCode 5.1.1

Problem: Crash in obj_msgsend on addObject message to a NSMutableArray

Disclaimer: I'm new to Objective-C, so this could an obvious mistake. But it's mysterious.

Details:

I've been able to prune the problem down to a small test case (thankfully), though the exact manifestation of the problem is different from the full application.

Here's the @interface:

@interface ObjCQueue : NSObject
+ (void) push: (NSString *)calEvent;
+ (NSString *) pop;
@end

Here's the Objective-C class implementation.

#import <Foundation/Foundation.h>
#include "ObjcQueue.h"

NSMutableArray *qArray;

@implementation ObjCQueue
{

}

+ (void) init
{
    qArray =  [[NSMutableArray alloc] init]; 
    //    NSLog(@"(init)qArray class is: %@\n", NSStringFromClass([qArray class]));
}

+ (void) push:(NSString *)calEvent
{
    [qArray addObject:calEvent];
} 

+ (NSString *) pop
{
    // This will return nil if there's no first object
    NSString *retEvent = [qArray objectAtIndex:0];
    // Don't delete the front of the queue if nothing is there
    if (retEvent != nil)
        [qArray removeObjectAtIndex:0];

    return retEvent;
}
@end

and main.m does this:

int main(int argc, const char * argv[])
{
    @autoreleasepool {     
        [ObjCQueue init];
        [ObjCQueue push:@"Pushed thing"];
        NSLog(@"Popped: %@\n", [ObjCQueue pop]);
    }
    return 0;
}

For the moment, let's ignore the possibility that how I'm doing this is totally wrong (we'll get back to that).

If I run this code as-is, I get a crash in objc_msgSend called by the addObject message sent from [ObjCQueue push:]

The mystery part is, if I uncomment the NSLog call in [ObjCQueue init] everything runs just fine.

In the larger application, I see a different issue. The failure also occurred in the push method, except the run-time error I got said that addObject was an invalid selector. When I check the type of qArray in that case, it has a type of NSDictionary (that's from memory, it wasn't spelled exactly that way) instead of NSMutableArray . Also, in the larger application, adding the NSLog call in the init method makes everything run smoothly.

In this smaller example, the type of qArray always appears to be NSMutableArray .

In other answers to similar questions , the implication is that the object corresponding to qArray is getting overwritten, and/or released prematurely. I don't see how that could happen here, since it's global, and ObjCQueue only has class methods and no instance of it is created. [ObjCQueue init] is only called once.

One other bit of data: In this smaller case, qArray gets displayed differently depending where (in the debugger) it's displayed.

In init , in the case where it crashes, immediately after qArray gets its value, the debugger shows:

Printing description of qArray:
<__NSArrayM 0x10010a680>(
)

But in push , just before the addObject method is called, the debugger shows:

Printing description of qArray:
(NSMutableArray *) qArray = 0x000000010010a680

The value is the same, but the type is kinda sorta different (maybe). In the case with no crash, the display is identical in both cases (they're both the same as the first display)

This may not be the best way (or it may be a blatantly wrong way) to initialize qArray , and I can accept that. But why would the behavior change with the addition of the NSLog call?

Any help/insights will be appreciated.

-Eric

PS Here's the XCode project: Bug Test

The problem is because ARC is releasing qArray before you called push so you're calling on an object that is already released. A good solution to this problem would be to either change your class to an actual instance, or create a singleton so that ARC knows to retain the array rather than just releasing it right after you init.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM