2017-12-07 5 views
0

Manchmal tritt in meiner App ein schwerwiegender Fehler mit dem Fehlerprotokoll EXC_BAD_ADDRESS auf.Wie löst man es (EXC_BAD_ADDRESS in Objective-C)?

Was ist die Ursache meines Codes?

Crashlog

0. Crashed: GGMutableDictionary Isolation Queue 
0 libobjc.A.dylib    0x184e2c150 objc_msgSend + 16 
1 CoreFoundation     0x1862e0d04 -[NSDictionary descriptionWithLocale:indent:] + 916 
2 CoreFoundation     0x1862e0dac -[NSDictionary descriptionWithLocale:indent:] + 1084 
3 Foundation      0x186da35a4 _NSDescriptionWithLocaleFunc + 76 
4 CoreFoundation     0x1863788bc __CFStringAppendFormatCore + 8440 
5 CoreFoundation     0x18637678c _CFStringCreateWithFormatAndArgumentsAux2 + 244 
6 Foundation      0x186da3418 +[NSString stringWithFormat:] + 68 
7 app       0x10019f4b8 -[TinyDB saveAsync] + 4296963256 
8 app       0x10019c86c __26-[TinyDB putString:value:]_block_invoke + 4296951916 
9 libdispatch.dylib    0x18526e9a0 _dispatch_client_callout + 16 
10 libdispatch.dylib    0x18527bee0 _dispatch_barrier_sync_f_invoke + 84 
11 app       0x10019c7e0 -[TinyDB putString:value:] + 4296951776 

Quelldatei

Diese Klasse asynchron von vielen anderen Klasse verwendet wird. Diese Klasse sollte Thread-sicher sein. Der schwerwiegende EXC_BAD_ADDRESS-Fehler tritt jedoch in der saveAsync-Methode auf. Ich denke, weakDictionaryRef oder isolationQueue Variablen werden freigegeben. Ich möchte dieses Problem beheben. Was sollte ich in diesem Code beheben? Vielen Dank für Ihren Rat.

TinyDB.h Datei

@interface TinyDB : NSObject 

@property (nonatomic, retain) NSString * docPath; 
// @property (nonatomic, retain) NSMutableDictionary * dictionary; 
@property (nonatomic, retain) NSFileManager * fileManager; 
@property (nonatomic, retain) NSString * dir; 
@property (nonatomic, assign) BOOL flagWrite; 
- (instancetype)initWithFile:(NSString *)file; 
- (NSString *)getDocPath; 
- (void)putDouble:(NSString *)key value:(double)value; 
- (void)putInt:(NSString *)key value:(NSInteger)value; 
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value; 
- (void)putString:(NSString *)key value:(NSString *)value; 
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value; 
- (void)putLong:(NSString *)key value:(NSInteger)value; 
- (void)putBool:(NSString *)key value:(BOOL)value; 
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value; 
- (id)get:(NSString *)key; 
- (NSMutableArray *)getMutableArray:(NSString *)key; 
- (BOOL)has:(NSString *)key; 
- (void)saveAsync; 
- (void)save; 
- (NSString *)jsonString; 
- (NSString *)stringify:(id)obj; 
- (NSString *)getSet:(id)value; 
- (NSString *)getPairSet:(NSString *)key value:(id)value; 
- (NSMutableDictionary*)getMutableDictionary:(NSString*)key; 
- (NSString *)getString:(NSString *)key; 
- (BOOL)getBool:(NSString*)key; 
- (NSArray *)allKeys; 
- (void)removeObjectForKey:(NSString*)key; 
@end 

TinyDB.m Datei

@implementation TinyDB 
{ 
@private dispatch_queue_t isolationQueue_; 
@private __strong NSMutableDictionary * _myDictionary; 
} 
@synthesize docPath=docPath,fileManager=fileManager,dir=dir,flagWrite=flagWrite; 
BOOL flagOnSave = false; 
BOOL flagWrite = true; 
NSString* dir; 
NSString* docPath = @""; 
NSLock* _dicLock=nil; 
NSFileManager* fileManager; 
__weak id _weakDictionaryRef; 

-(id)initWithFile:(NSString *)file{ 
    self = [super init]; 
    docPath = file; 
    // ########################################## 
    isolationQueue_ = dispatch_queue_create([@"GGMutableDictionary Isolation Queue" UTF8String], DISPATCH_QUEUE_CONCURRENT); 
    // ########################################## 
    fileManager = [NSFileManager defaultManager]; 
    dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) firstObject]; 
    dir = [NSString stringWithFormat:@"%@/myapp/",dir]; 
    BOOL flagFileExist = [fileManager fileExistsAtPath:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]]; 
    _myDictionary = [[NSMutableDictionary alloc] init]; 
    if(flagFileExist){ 
     [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Found!!! %@ --> ",file]]; 
     @try{ 
      NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]]; 
      _myDictionary = [[NSMutableDictionary alloc] initWithDictionary:dic]; 
     }@catch(NSException * e){ 
      _myDictionary = [[NSMutableDictionary alloc] init]; 
     }@finally{ 
     } 
    }else{ 
     [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Not Found!!!--> %@ ",file]]; 
     _myDictionary = [[NSMutableDictionary alloc] init]; 
    } 
    _weakDictionaryRef = _myDictionary; 
    [self saveAsync]; 
    return self; 
} 
-(void)putString:(NSString*)key value:(NSString*)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if(value == nil){ 
      return; 
     } 
     @try{ 
      [_myDictionary setObject:value forKey:key]; 
     }@catch(NSException* e){ 
      NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary]; 
      _myDictionary = buff; 
      _weakDictionaryRef = _myDictionary; 
      dispatch_barrier_sync(isolationQueue_, ^{ 
       [_myDictionary setObject:value forKey:key]; 
      }); 
     }@finally{ 
     } 
     [self saveAsync]; 
    }); 
} 

- (void)putDouble:(NSString *)key value:(double)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     [_myDictionary setObject:[[NSNumber alloc] initWithDouble:value] forKey:key]; 
     [self saveAsync]; 
    }); 
} 
- (void)putInt:(NSString *)key value:(NSInteger)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     @try{ 
      [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key]; 
     }@catch(NSException* e){ 
      NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary]; 
      _myDictionary = buff; 
      _weakDictionaryRef = _myDictionary; 
      [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key]; 
     }@finally{ 
     } 
     [self saveAsync]; 
    }); 
} 
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if(key != nil && value != nil){ 
      [_myDictionary setObject:value forKey:key]; 
      [self saveAsync]; 
     } 
    }); 
} 
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     TinyDB* db = value; 
     NSString* docuPath = [db getDocPath]; 
     @try{ 
      [_myDictionary setObject:docuPath forKey:key]; 
     }@catch(NSException* e){ 
      NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary]; 
      _myDictionary = buff; 
      _weakDictionaryRef = _myDictionary; 
      dispatch_barrier_sync(isolationQueue_, ^{ 
       [_myDictionary setObject:docuPath forKey:key]; 
      }); 
     }@finally{ 

     } 
     [self saveAsync]; 
    }); 
} 
- (void)putLong:(NSString *)key value:(NSInteger)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key]; 
     [self saveAsync]; 
    }); 
} 
- (void)putBool:(NSString *)key value:(BOOL)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     [_myDictionary setObject:[[NSNumber alloc] initWithBool:value] forKey:key]; 
     [self saveAsync]; 
    }); 
} 
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     [_myDictionary setObject:value forKey:key]; 
     [self saveAsync]; 
    }); 
} 
-(void)removeObjectForKey:(NSString*)key{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if(_myDictionary != nil && [_myDictionary objectForKey:key] != nil){ 
      [_myDictionary removeObjectForKey:key]; 
     } 
    }); 
} 
-(void) save{ 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     @try { 
      // NSLog([NSString stringWithFormat:@"writeToFile Error : orgPath = %@/%@.myapp/%@",dir,docPath, self.dictionary ]); 
      // NSMutableDictionary* nsDic = self.dictionary; 
      if(_myDictionary != nil){ 
       NSDictionary * _dictionary = 
       (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, 
                     (__bridge CFPropertyListRef)(_myDictionary), 
                     kCFPropertyListImmutable)); 
       if(_dictionary != nil){ 
        [_dictionary writeToFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath] atomically: false]; 
       } 
      } 
     }@catch (NSException *exception) { 
      _myDictionary = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary]; 
      _weakDictionaryRef = _myDictionary; 
     }@finally { 
     } 
    }); 
} 
// ################################################################ 
// normal function 
- (NSString *)jsonString{ 
    __block NSString* buff = @""; 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if(_myDictionary != nil){ 
      NSDictionary * _dictionary = nil; 
      // dispatch_barrier_sync(isolationQueue_, ^{ 
      _dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, 
                       (__bridge CFPropertyListRef)(_myDictionary), 
                       kCFPropertyListImmutable)); 
      if(_dictionary != nil){ 
       buff = [self stringify:_dictionary]; 
      } 
     }else{ 
      NSLog(@"buff = [self stringify:_myDictionary]; is nil "); 
     } 

    }); 
    return buff; 
} 
- (NSString *)stringify:(id)obj{ 
    if([obj isKindOfClass:[NSDictionary class]]){ 
     int idx = 0; 
     NSString* buff = @"{"; 
     if(obj != nil){ 
      NSDictionary* dic = [NSDictionary dictionaryWithDictionary:obj]; //obj; 
      for(NSString* key in dic){ 
       id value = [dic objectForKey:key]; 
       if(idx != 0){ 
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","]; 
       } 
       buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getPairSet:key value:value]]; 
       idx++; 
      } 
     } 
     buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"}"]; 
     return buff; 
    }else if([obj isKindOfClass:[NSArray class]]){ 
     int idx = 0; 
     NSString* buff = @"["; 
     if(obj != nil){ 
      NSMutableArray* _a = [[NSMutableArray alloc] init]; 
      for(int ai = 0; ai < [obj count]; ai++){ 
       if([obj objectAtIndex:ai] != nil){ 
        [_a addObject:[obj objectAtIndex:ai]]; 
       } 
      } 
      NSArray* arr = [NSArray arrayWithArray:_a]; //obj; 
      for(id value in arr){ 
       if(idx != 0){ 
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","]; 
       } 
       buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getSet:value]]; 
       idx++; 
      } 
     } 
     buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"]"]; 
     return buff; 
    }else{ 
     return [self getSet:obj]; 
    } 
} 
- (NSString *)getSet:(id)value{ 
    NSString* buff = @""; 
    if([value isKindOfClass:[NSString class]]){ 
     buff = [[NSString alloc] initWithFormat:@"%@\"%@\"",buff,value]; 
    }else if([value isKindOfClass:[NSNumber class]]){ 
     NSNumber* val = value; 
     buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[val stringValue]]; 
    }else{ 
     buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self stringify:value]]; 
    } 
    return buff; 
} 
- (NSString *)getPairSet:(NSString *)key value:(id)value{ 
    NSString* buff = @""; 
    if([value isKindOfClass:[NSString class]]){ 
     buff = [[NSString alloc] initWithFormat:@"%@\"%@\":\"%@\"",buff,key,value]; 
    }else if([value isKindOfClass:[NSNumber class]]){ 
     buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[value stringValue]]; 
    }else{ 
     buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[self stringify:value]]; 
    } 
    return buff; 
} 
-(NSMutableDictionary*)getMutableDictionary:(NSString*)key{ 
    NSMutableDictionary* dic = [[NSMutableDictionary alloc] init]; 
    id obj = [_myDictionary objectForKey:key]; 
    if(obj != nil){ 
     dic = [[NSMutableDictionary alloc] initWithDictionary:obj]; 
    } 
    return dic; 
} 
-(NSArray *)allKeys{ 
    __block NSArray* arr = nil; 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if(_myDictionary != nil){ 
      arr = [_myDictionary allKeys]; 
     } 
    }); 
    return arr; 
} 
- (NSString *)getDocPath{ 
    return docPath; 
} 
- (id)get:(NSString *)key{ 
    __block id _obj = nil; 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     _obj = [_myDictionary objectForKey:key]; 
    }); 
    return _obj; 
} 
- (NSString *)getString:(NSString *)key{ 
    __block NSString* returnStr = @""; 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if([_myDictionary objectForKey:key]==nil){ 
      returnStr = @""; 
     } 
     if([[_myDictionary objectForKey:key] isKindOfClass:[NSString class]]){ 
      returnStr = [_myDictionary objectForKey:key]; 
     }else{ 
      returnStr = @""; 
     } 
    }); 
    return returnStr; 
} 
- (BOOL)getBool:(NSString*)key{ 
    __block BOOL flag = false; 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if([_myDictionary objectForKey:key]==nil){ 
      flag = NO; 
     } 
     if([[_myDictionary objectForKey:key] isKindOfClass:[NSNumber class]]){ 
      NSNumber* boolValue = [_myDictionary objectForKey:key]; 
      if([boolValue boolValue] == YES){ 
       flag = YES; 
      }else{ 
       flag = NO; 
      } 
     }else{ 
      flag = NO; 
     } 
    }); 
    return flag; 
} 
- (NSMutableArray *)getMutableArray:(NSString *)key{ 
    __block NSMutableArray* _arr = nil; 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     _arr = [_myDictionary objectForKey:key]; 
    }); 
    return _arr; 
} 
- (BOOL)has:(NSString *)key{ 
    __block BOOL flag = false; 
    dispatch_barrier_sync(isolationQueue_, ^{ 
     if([_myDictionary objectForKey:key] != nil){ 
      flag = true; 
     }else{ 
      flag = false; 
     } 
    }); 
    return flag; 
} 
// ######################### 
// save function 
int flagTest = 0; 
bool mark = 0; 
NSTimer* saveTimer = nil; 
-(void)saveAsync{ 
    @try { 
     [BSDebugger log:[NSString stringWithFormat:@"_weakDictionaryRef : %@ ",_weakDictionaryRef ]]; 
     if(_myDictionary != nil){ 
      if(_weakDictionaryRef != nil){ 
       NSDictionary * _dictionary = nil; 
       _dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, 
                        (__bridge CFPropertyListRef)(_myDictionary), 
                        kCFPropertyListImmutable)); 
       @try{ 
        flagOnSave = true; 
        UIBackgroundTaskIdentifier taskID = [myappCore beginBackgroundUpdateTask]; 
        flagWrite = false; 
        NSString* orgPath = [[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath ]; 
        @try { 
         if(_dictionary != nil){ 
          [_dictionary writeToFile:orgPath atomically:YES]; 
         } 
        }@catch (NSException *exception) { 
         [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exception callStackSymbols]]]; 
        }@finally { 
        } 
        flagWrite = true; 
        flagOnSave = false; 
        [myappCore endBackgroundUpdateTask:taskID]; 
       }@catch (NSException *exceptionMain) { 
        [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exceptionMain callStackSymbols]]]; 
       }@finally { 
        _dictionary = nil; 
       } 
       return; 
       // }); 
      } 
     } 
    }@catch (NSException *exception) { 
    }@finally { 
     // [_dicLock unlock]; 
    } 
} 
@end 

Antwort

0

Einige Ideen:

Schalten Sie Zombies (How to enable NSZombie in Xcode). Sie erhalten dann mehr Informationen über das Objekt, das den Absturz verursacht hat.

Wenn Sie den Fehler nach Belieben ausführen können, setzen Sie einen Haltepunkt oben auf saveAsync und durchlaufen Sie ihn.

Ändern Sie die stringWithFormat Anrufe irgendwie, so dass sie nichts verweisen, das freigegeben werden könnte und sehen, ob das Problem verschwindet. Wenn ja, wissen Sie, was das verursacht hat.

Ich finde es manchmal hilft zu überschreiben retain und release in Objekten, die ich misstrauisch bin und entweder etwas ausdrucken oder setzen Sie einen Haltepunkt, damit ich sehen kann, wer ein Objekt überfreigabe sein könnte.