iOS 7 porting 32 bit to 64 bit Crash - objective-c

Why does this code crash in 64 bit? - It works fine 32 bit.
It's loading a nib for a UIView
- (id) awakeAfterUsingCoder:(NSCoder*)aDecoder {
BOOL theThingThatGotLoadedWasJustAPlaceholder = ([[self subviews] count] == 0);
if (theThingThatGotLoadedWasJustAPlaceholder) {
ALTimelineView* theRealThing = [[self class] loadFromNib];
// pass properties through
theRealThing.frame = self.frame;
theRealThing.autoresizingMask = self.autoresizingMask;
theRealThing.alpha = self.alpha;
theRealThing.hidden = self.hidden;
[theRealThing internalInit];
// convince ARC that we're legit
CFRelease((__bridge const void*)self);
CFRetain((__bridge const void*)theRealThing);
return theRealThing;
}
return self;
}
loadFromNib
+ (id) loadFromNib {
NSString* nibName = NSStringFromClass([self class]);
NSArray* elements = [[NSBundle mainBundle] loadNibNamed:nibName owner:nil options:nil];
for (NSObject* anObject in elements) {
if ([anObject isKindOfClass:[self class]]) {
return anObject;
}
}
return nil;
}
The error I'm getting is EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

EXC_I386_GPFLT is surely referring to "General Protection fault", which is the x86's way to tell you that "you did something that you are not allowed to do". It typically DOESN'T mean that you access out of memory bounds, but it could be that your code is going out of bounds and causing bad code/data to be used in a way that makes for an protection violation of some sort.
check this Reference Link for good explanation of EXC_I386_GPFLT

Related

How can I convince XCode's Analyzer that this isn't a leak?

The static analyzer is informing me that the following code has a potential leak. I don't understand how there's any room for a leak. Further, I don't understand how the analyzer can be so helpful across the entire project yet miss something this easy.
My assumption is that the analyzer is right and I am leaking. But how?
+ (McFieldDefinition *) freeformFieldDefinition {
return [[[McFieldDefinition alloc] initWithText:#"0201FFM100"] autorelease];
}
Thanks!
Sorry for posting this question. I finally found an answer here: https://stackoverflow.com/a/15668026/300986.
The problem was in my init method:
- (id) initWithText:(NSString *)text {
if (!text) return nil;
if ([text length] < 7) return nil;
self = [self init];
if (self) {
// do stuff
}
return self;
}
Those two guard clauses return nil if I don't like the text variable. self is already alloc'ed by that point, so it's Analyzer 1, bmauter 0.
Here's my new version:
- (id) initWithText:(NSString *)text {
self = [self init];
if (!self) return nil;
if (!text || [text length] < 7) {
[self release];
return nil;
}
// do stuff
return self;
}

Remove object from an array stored in a singleton

Im working with a singleton to store some data, her's the implementation
static ApplicationData *sharedData = nil;
#implementation ApplicationData
#synthesize list;
+ (id)sharedData
{
static dispatch_once_t dis;
dispatch_once(&dis, ^{
if (sharedData == nil) sharedData = [[self alloc] init];
});
return sharedData;
}
- (id)init
{
if (self = [super init])
{
list = [[NSMutableArray alloc]init];
}
return self;
}
if list have less than 3 (2<) object i the app crash with "index 0 beyond bounds for empty array"
// NSMutableArray *anArray = [[NSMutableArray alloc]initWithObjects:#"", nil];
while ([[[ApplicationData sharedData]list] lastObject] != nil)
{
File *file = [[[ApplicationData sharedData]list] lastObject];
BOOL isDir;
if (![[NSFileManager defaultManager] fileExistsAtPath:file.filePath isDirectory:&isDir])
{
NSMutableDictionary *tmpDic = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:file.fileName,file.filePath,logEnteryErrorfileNotFoundDisplayName,[formatter stringFromDate:[NSDate date]], nil] forKeys:[NSArray arrayWithObjects:logShredFileName,logShredFilePath,logShredStatue,logShredDate, nil]];
[logArray addObject:tmpDic];
errorOccured = YES;
[[[ApplicationData sharedData]list] removeLastObject];
continue;
}
... other code
}
if i use the anArray that work perfectly.
what is the problem ?
That's totally weird, you've probably did something else to achieve this. Why don't you use - (void)removeAllObjects?
Maybe you remove objects in the while cycle the last line, ie:
while ([[[ApplicationData sharedData]list] count] != 0)
{
// remove object from list
// ...
[[[ApplicationData sharedData]list] removeLastObject];
}
And just a note, you don't need to check if (sharedData == nil) in sharedData as far as it's guaranteed to be executed only once. (unless you do something outside to your static variable, but that's not how it's supposed to be done I believe)

NSArray crashes the app when accessing it

I have a problem with accessing/setting an object from/to a NSArray returned with the CFPreferencesCopyAppValue() method. My app crashes in this case whereas when I alloc/init it myself, everything works well.
CFArrayRef cfArray;
if ((cfArray = (CFArrayRef)CFPreferencesCopyAppValue(CFSTR("buttonsOrder"), appID))) {
NSArray *castedArray = [(NSArray *)cfArray retain];
NSLog(#"castedArray : %#", castedArray);
buttonsOrder = [castedArray mutableCopy];
NSLog(#"buttonsOrder : %#", buttonsOrder);
CFRelease(cfArray);
[castedArray release];
castedArray = nil;
}
else {
buttonsOrder = [[NSMutableArray alloc] init];
for (NSMutableDictionary *info in togglesInfo) {
[buttonsOrder addObject:[info objectForKey:#"buttonIdentifier"]];
}
}
PS : NSLog() shows me that CFArray is returned well and is casted to NSArray and then NSMutableArray well too.
Any idea ?
Edit :
Here is how I modofy the array :
- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
NSUInteger fromIndex = [fromIndexPath row];
NSUInteger toIndex = [toIndexPath row];
if (fromIndex == toIndex)
return;
NSString *movedButtonId = [[[buttonsOrder objectAtIndex:fromIndex] retain] autorelease];
[buttonsOrder removeObjectAtIndex:fromIndex];
[buttonsOrder insertObject:movedButtonId atIndex:toIndex];
}
If you crash while trying to add an object to a mutable array, that usually means you're attempting to add a nil object. The only place (in your code snippet above) where I see you adding anything to your mutable array is in the case where you didn't get a valid "cfArray" from CFPreferences. You should make sure "[info objectForKey:#"buttonIdentifier"]" isn't returning nil.
Check to make sure you're not throwing an exception. Or if that's not it, say what your crash really is (it'll say in the Console log of Xcode).

Something is wrong with singleton...unable adding a child because it is nil

I use a singleton the first time and I don't really know how to implement it...
Ok I need to explain some things:
In Hexagon.h (which inherits from CCNode) I want to create multiple sprites (here referred to as "hexagons"). However, they are not added to the scene yet. They are being added in the HelloWorldLayer.m class by calling Hexagon *nHex = [[Hexagon alloc]init]; . Is that correct ? Is it then iterating through the for loop and creating all hexagons or only one ?
Well anyways, I have a singleton class which has to handle all the public game state information but retrieving is not possible yet.For instance I cannot retrieve the value of existingHexagons, because it returns (null) objects. Either I set the objects wrongly or I am falsely retrieving data from the singleton. Actually, I would even appreciate an answer for one of these questions. Please help me. If something is not clear, please add a comment and I'll try to clarify it.
What I have right now is the following:
GameStateSingleton.h
#import <Foundation/Foundation.h>
#interface GameStateSingleton : NSObject{
NSMutableDictionary *existingHexagons;
}
+(GameStateSingleton*)sharedMySingleton;
-(NSMutableDictionary*)getExistingHexagons;
#property (nonatomic,retain) NSMutableDictionary *existingHexagons;
#end
GameStateSingleton.m
#import "GameStateSingleton.h"
#implementation GameStateSingleton
#synthesize existingHexagons;
static GameStateSingleton* _sharedMySingleton = nil;
+(GameStateSingleton*)sharedMySingleton
{
#synchronized([GameStateSingleton class])
{
if (!_sharedMySingleton)
[[self alloc] init];
return _sharedMySingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([GameStateSingleton class])
{
NSAssert(_sharedMySingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedMySingleton = [super alloc];
return _sharedMySingleton;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
}
return self;
}
#end
Hexagon.m
-(CCSprite *)init{
if( (self=[super init])) {
NSString *mainPath = [[NSBundle mainBundle] bundlePath];
NSString *levelConfigPlistLocation = [mainPath stringByAppendingPathComponent:#"levelconfig.plist"];
NSDictionary *levelConfig = [[NSDictionary alloc] initWithContentsOfFile:levelConfigPlistLocation];
NSString *currentLevelAsString = [NSString stringWithFormat:#"level%d", 1];
NSArray *hexPositions;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
hexPositions = [[levelConfig valueForKey:currentLevelAsString] valueForKey:#"hexpositionIpad"];
}
else{
hexPositions = [[levelConfig valueForKey:currentLevelAsString] valueForKey:#"hexpositionIphone"];
}
NSString *whichType = [NSString stringWithFormat:#"glass"];
CGSize screenSize = [CCDirector sharedDirector].winSize;
if ([whichType isEqualToString:#"stone"]){
hexagon = [CCSprite spriteWithFile:#"octagonstone.png"];
}else if([whichType isEqualToString: #"glass"]){
hexagon = [CCSprite spriteWithFile:#"octagoncolored1.png"];
}else if([whichType isEqualToString: #"metal"]){
hexagon = [CCSprite spriteWithFile:#"octagonmetal.png"];
}
NSMutableDictionary *eHexagons =[[GameStateSingleton sharedMySingleton] getExistingHexagons];
for (int i=0;i < [hexPositions count];i++){
CGPoint location = CGPointFromString([hexPositions objectAtIndex:i]);
CGPoint nLocation= ccp(screenSize.width/2 + 68 * location.x,screenSize.height/2 + 39 * location.y);
NSString *aKey = [NSString stringWithFormat:#"hexagon%d",i];
hexagon =[CCSprite spriteWithFile:#"octagoncolored1.png"];
hexagon.position = nLocation;
[eHexagons setObject:hexagon forKey:aKey];
[self addChild:[eHexagons valueForKey:aKey] z:3];
[[GameStateSingleton sharedMySingleton]setExistingHexagons:eHexagons];
}
NSLog(#"these are the existinghexagons %#", existingHexagons);
//This returns a dictionary with one (null) object
}
return hexagon;
}
HelloWorldLayer.m -> -(id)init method
Hexagon *nHex = [[Hexagon alloc]init];
First of all, it returns null because the existingHexagons array has never been initialized in the first place. Go to the init function of your singleton and add:
existingHexagons = [[NSMutableArray alloc]init];
As for your For Loop question, I did not get it. I recommend making one StackOverflow question per query instead of putting two in one.

NSMutableDictionary thread safety

I have a question on thread safety while using NSMutableDictionary.
The main thread is reading data from NSMutableDictionary where:
key is NSString
value is UIImage
An asynchronous thread is writing data to above dictionary (using NSOperationQueue)
How do I make the above dictionary thread safe?
Should I make the NSMutableDictionary property atomic? Or do I need to make any additional changes?
#property(retain) NSMutableDictionary *dicNamesWithPhotos;
NSMutableDictionary isn't designed to be thread-safe data structure, and simply marking the property as atomic, doesn't ensure that the underlying data operations are actually performed atomically (in a safe manner).
To ensure that each operation is done in a safe manner, you would need to guard each operation on the dictionary with a lock:
// in initialization
self.dictionary = [[NSMutableDictionary alloc] init];
// create a lock object for the dictionary
self.dictionary_lock = [[NSLock alloc] init];
// at every access or modification:
[object.dictionary_lock lock];
[object.dictionary setObject:image forKey:name];
[object.dictionary_lock unlock];
You should consider rolling your own NSDictionary that simply delegates calls to NSMutableDictionary while holding a lock:
#interface SafeMutableDictionary : NSMutableDictionary
{
NSLock *lock;
NSMutableDictionary *underlyingDictionary;
}
#end
#implementation SafeMutableDictionary
- (id)init
{
if (self = [super init]) {
lock = [[NSLock alloc] init];
underlyingDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void) dealloc
{
[lock_ release];
[underlyingDictionary release];
[super dealloc];
}
// forward all the calls with the lock held
- (retval_t) forward: (SEL) sel : (arglist_t) args
{
[lock lock];
#try {
return [underlyingDictionary performv:sel : args];
}
#finally {
[lock unlock];
}
}
#end
Please note that because each operation requires waiting for the lock and holding it, it's not quite scalable, but it might be good enough in your case.
If you want to use a proper threaded library, you can use TransactionKit library as they have TKMutableDictionary which is a multi-threaded safe library. I personally haven't used it, and it seems that it's a work in progress library, but you might want to give it a try.
Nowadays you'd probably go for #synchronized(object) instead.
...
#synchronized(dictionary) {
[dictionary setObject:image forKey:name];
}
...
#synchronized(dictionary) {
[dictionary objectForKey:key];
}
...
#synchronized(dictionary) {
[dictionary removeObjectForKey:key];
}
No need for the NSLock object any more
after a little bit of research I want to share with you this article :
Using collection classes safely with multithreaded applications
http://developer.apple.com/library/mac/#technotes/tn2002/tn2059.html
It looks like notnoop's answer may not be a solution after all. From threading perspective it is ok, but there are some critical subtleties. I will not post here a solution but I guess that there is a good one in this article.
I have two options to using nsmutabledictionary.
One is:
NSLock* lock = [[NSLock alloc] init];
[lock lock];
[object.dictionary setObject:image forKey:name];
[lock unlock];
Two is:
//Let's assume var image, name are setup properly
dispatch_async(dispatch_get_main_queue(),
^{
[object.dictionary setObject:image forKey:name];
});
I dont know why some people want to overwrite setting and getting of mutabledictionary.
Even the answer is correct, there is an elegant and different solution:
- (id)init {
self = [super init];
if (self != nil) {
NSString *label = [NSString stringWithFormat:#"%#.isolation.%p", [self class], self];
self.isolationQueue = dispatch_queue_create([label UTF8String], NULL);
label = [NSString stringWithFormat:#"%#.work.%p", [self class], self];
self.workQueue = dispatch_queue_create([label UTF8String], NULL);
}
return self;
}
//Setter, write into NSMutableDictionary
- (void)setCount:(NSUInteger)count forKey:(NSString *)key {
key = [key copy];
dispatch_async(self.isolationQueue, ^(){
if (count == 0) {
[self.counts removeObjectForKey:key];
} else {
self.counts[key] = #(count);
}
});
}
//Getter, read from NSMutableDictionary
- (NSUInteger)countForKey:(NSString *)key {
__block NSUInteger count;
dispatch_sync(self.isolationQueue, ^(){
NSNumber *n = self.counts[key];
count = [n unsignedIntegerValue];
});
return count;
}
The copy is important when using thread unsafe objects, with this you could avoid the possible error because of unintended release of the variable. No need for thread safe entities.
If more queue would like to use the NSMutableDictionary declare a private queue and change the setter to:
self.isolationQueue = dispatch_queue_create([label UTF8String], DISPATCH_QUEUE_CONCURRENT);
- (void)setCount:(NSUInteger)count forKey:(NSString *)key {
key = [key copy];
dispatch_barrier_async(self.isolationQueue, ^(){
if (count == 0) {
[self.counts removeObjectForKey:key];
} else {
self.counts[key] = #(count);
}
});
}
IMPORTANT!
You have to set an own private queue without it the dispatch_barrier_sync is just a simple dispatch_sync
Detailed explanation is in this marvelous blog article.
In some cases you might NSCache class. The documentation claims that it's thread safe:
You can add, remove, and query items in the cache from different threads without having to lock the cache yourself.
Here is article that describes quite useful tricks related to NSCache