2009-09-24 31 views
0

在我们的多用户应用程序中,我们不断与数据库进行交互。我们有一个通用的类,通过它将POST查询发送到数据库并获取xml文件作为回报。我们使用NSXMLParser的委托来解析获取的文件。我们面临的问题是,我们通常在应用程序闲置时遇到很多崩溃,并且数据库中的数据更改是通过每隔几秒后调用一次的定时器在后台获取的。我们还通过try和catch处理了错误处理,但在这种情况下它证明是没有用的,并且大多数应用程序崩溃并且出现以下错误: 异常类型:EXC_BAD_ACCESS(SIGBUS) 异常代码:KERN_PROTECTION_FAILURE at 0x0000000000000020 奇怪的是,很多时候,在后台获取更新的数据的工作非常好,同样的方法在类似的条件下成功执行,但突然之间崩溃在其中之一。 我们正在使用的代码如下:应用程序崩溃时使用定时器从数据库获取更新信息并将其存储在本地数据结构中


// we are using timer in this way: 
chkOnlineUser=[NSTimer scheduledTimerWithTimeInterval:15 target:mmObject selector:@selector(threadOnlineUser) userInfo:NULL repeats:YES]; 


// this method being called in timer 
-(void)threadOnlineUser{//HeartBeat in Thread 
    [NSThread detachNewThreadSelector:@selector(onlineUserRefresh) toTarget:self withObject:nil]; 
} 

// this performs actual updation 
-(void)onlineUserRefresh{ 
    NSAutoreleasePool *pool =[[NSAutoreleasePool alloc]init]; 
    @try{ 
     if(chkTimer==1){ 
      return; 
     } 
     chkTimer=1; 

     if([allUserArray count]==0){ 
      [user parseXMLFileUser:@"all" andFlag:3]; 
      [allUserArray removeAllObjects]; 
      [allUserArray addObjectsFromArray:[user users]]; 
     } 
     [objHeartBeat parseXMLFile:[loginID intValue] timeOut:10]; 
     NSMutableDictionary *tDictOL=[[NSMutableDictionary alloc] init]; 
     tDictOL=[objHeartBeat onLineList]; 

     NSArray *tArray=[[NSArray alloc] init]; 
     tArray=[[tDictOL objectForKey:@"onlineuser"] componentsSeparatedByString:@","]; 
     [loginUserArray removeAllObjects]; 
     for(int l=0;l less than [tArray count] ;l++){ 
      int t;//=[[tArray objectAtIndex:l] intValue]; 
      if([[allUserArray valueForKey:@"Id"] containsObject:[tArray objectAtIndex:l]]){ 
       t = [[allUserArray valueForKey:@"Id"] indexOfObject:[tArray objectAtIndex:l]]; 
       [loginUserArray addObject:[allUserArray objectAtIndex:t]]; 
      } 
     } 
     [onlineTable reloadData]; 

     [logInUserPopUp removeAllItems]; 
     if([loginUserArray count]==1){ 
      [labelLoginUser setStringValue:@"Only you are online"]; 
      [logInUserPopUp setEnabled:YES]; 
     }else{ 
      [labelLoginUser setStringValue:[NSString stringWithFormat:@" %d users online",[loginUserArray count]]]; 
      [logInUserPopUp setEnabled:YES]; 
     } 

     NSMenu *menu = [[NSMenu alloc] initWithTitle:@"menu"]; 
     NSMenuItem *itemOne = [[NSMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:@""]; 
     [menu addItem:itemOne]; 
     for(int l=0;l less than [loginUserArray count];l++){ 
      NSString *tempStr= [NSString stringWithFormat:@"%@ %@",[[[loginUserArray objectAtIndex:l] objectForKey:@"user_fname"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]],[[[loginUserArray objectAtIndex:l] objectForKey:@"user_lname"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; 
      if(![tempStr isEqualToString:@""]){ 
       NSMenuItem *itemOne = [[NSMenuItem alloc] initWithTitle:tempStr action:NULL keyEquivalent:@""]; 
       [menu addItem:itemOne]; 
      }else if(l==0){ 
       NSMenuItem *itemOne = [[NSMenuItem alloc] initWithTitle:tempStr action:NULL keyEquivalent:@""]; 
       [menu addItem:itemOne]; 
      } 
     } 
     [logInUserPopUp setMenu:menu]; 

     if([lastUpdateTime isEqualToString:@""]){ 
     }else { 
      [self fetchUpdatedInfo:lastUpdateTime]; 


      [self fetchUpdatedGroup:lastUpdateTime];// function same as fetchUpdatedInfo 
      [avObject fetchUpdatedInfo:lastUpdateTime];// function same as fetchUpdatedInfo 
      [esTVObject fetchUpdatedInfo:lastUpdateTime];// function same as fetchUpdatedInfo 
     } 

     lastUpdateTime=[[tDictOL objectForKey:@"lastServerTime"] copy]; 
    } 
    @catch (NSException * e) { 
     [queryByPost insertException:@"MainModule" inFun:@"onlineUserRefresh" excp:[e description] userId:[loginID intValue]]; 
     NSRunAlertPanel(@"Error Panel", @"Main Module- onlineUserRefresh....%@", @"OK", nil, nil,e); 
    } 
    @finally { 
     NSLog(@"Internal Update Before Bye"); 
     chkTimer=0; 
     NSLog(@"Internal Update Bye");// Some time application crashes after this log 

     // Some time application crahses after "Internal Update Bye" log 
    } 
} 

// The method which we are using to obtain updated data is of following form: 
-(void)fetchUpdatedInfo:(NSString *)UpdTime{ 
    @try { 
     if(initAfterLoginComplete==0){ 
      return; 
     } 

     [user parseXMLFileUser:UpdTime andFlag:[loginID intValue]]; 
     [tempUserUpdatedArray removeAllObjects]; 
     [tempUserUpdatedArray addObjectsFromArray:[user users]]; 
     if([tempUserUpdatedArray count]>0){ 
      if([contactsView isHidden]){ 
       [topContactImg setImage:[NSImage imageNamed:@"btn_contacts_off_red.png"]]; 
      }else { 
       [topContactImg setImage:[NSImage imageNamed:@"btn_contacts_red.png"]]; 
      } 
     }else { 
      return; 
     } 
     int chkprof=0; 
     for(int l=0;l less than [tempUserUpdatedArray count];l++){ 
      NSArray *tempArr1 = [allUserArray valueForKey:@"Id"]; 
      int s; 
      if([[[tempUserUpdatedArray objectAtIndex:l] objectForKey:@"Id"] intValue]==profile_Id){ 
       chkprof=1; 
      } 
      if([tempArr1 containsObject:[[tempUserUpdatedArray objectAtIndex:l] objectForKey:@"Id"]]){ 
       s = [tempArr1 indexOfObject:[[tempUserUpdatedArray objectAtIndex:l] objectForKey:@"Id"]]; 
       [allUserArray replaceObjectAtIndex:s withObject:[tempUserUpdatedArray objectAtIndex:l]]; 
      }else { 
       [allUserArray addObject:[tempUserUpdatedArray objectAtIndex:l]]; 
      } 

      NSArray *tempArr2 = [tempUser valueForKey:@"Id"]; 
      if([tempArr2 containsObject:[[tempUserUpdatedArray objectAtIndex:l] objectForKey:@"Id"]]){ 
       s = [tempArr2 indexOfObject:[[tempUserUpdatedArray objectAtIndex:l] objectForKey:@"Id"]]; 
       [tempUser replaceObjectAtIndex:s withObject:[tempUserUpdatedArray objectAtIndex:l]]; 
      }else { 
       [tempUser addObject:[tempUserUpdatedArray objectAtIndex:l]]; 
      } 
     } 

     NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"user_fname" ascending:YES]; 
     [tempUser sortUsingDescriptors:[NSMutableArray arrayWithObject:sortDescriptor]]; 
     [userListTableView reloadData]; 

     [groupsArray removeAllObjects]; 
     for(int z=0;z less than [tempGroups count];z++){ 
      NSMutableArray *tempMArr=[[NSMutableArray alloc] init]; 
      for(int l=0;l less than [allUserArray count];l++){ 
       if([[[allUserArray objectAtIndex:l] objectForKey:@"GroupId"] intValue]==[[[tempGroups objectAtIndex:z] objectForKey:@"group_id"] intValue]){ 
        [tempMArr addObject:[allUserArray objectAtIndex:l]]; 
       } 
      } 
      [groupsArray insertObject:tempMArr atIndex:z]; 
      [tempMArr release]; 
      tempMArr= nil; 
     } 

     for(int n=0;n less than [tempGroups count];n++){ 
      [[groupsArray objectAtIndex:n] addObject:[tempGroups objectAtIndex:n]]; 
     } 
     [groupsListOV reloadData]; 
     if(chkprof==1){ 
      [self profileShow:profile_Id]; 
     }else { 
     } 
     [self selectUserInTable:0]; 
    }@catch (NSException * e) { 
     NSRunAlertPanel(@"Error Panel", @"%@", @"OK", nil, nil,e); 
    } 
} 

// The method which we are using to frame select query and parse obtained data is: 
-(void)parseXMLForUser:(int)UId stringVar:(NSString*)stringVar{ 
    @try{ 

     if(queryByPost) 
      [queryByPost release]; 

     queryByPost=[QueryByPost new]; // common class used to invoke method to send request via POST method 

     //obtaining data for xml parsing 
     NSString *query=[NSString stringWithFormat:@"Select * from userinfo update_time >= '%@' AND NOT owner_id ='%d' ",stringVar,UId]; 

     NSData *obtainedData=[queryByPost executeQuery:query WithAction:@"query"]; // method invoked to perform post query 

     if(obtainedData==nil){ 
      // data not obtained so return 
      return; 
     } 

     // initializing dictionary to be obtained after parsing 
     if(obtainedDictionary) 
      [obtainedDictionary release]; 

     obtainedDictionary=[NSMutableDictionary new]; 

     // xml parsing 
     if (updatedDataParser) // airportsListParser is an NSXMLParser instance variable 
      [updatedDataParser release]; 

     updatedDataParser = [[NSXMLParser alloc] initWithData:obtainedData]; 
     [updatedDataParser setDelegate:self]; 
     [updatedDataParser setShouldResolveExternalEntities:YES]; 

     BOOL success = [updatedDataParser parse]; 

    } 
    @catch (NSException *e) { 
     NSLog(@"wtihin parseXMLForUser- parseXMLForUser:stringVar: - %@",[e description]); 
    } 

} 
//The method which will attempt to interact 4 times with server if interaction with it is found to be unsuccessful , is of following form: 
-(NSData*)executeQuery:(NSString*)query WithAction:(NSString*)doAction{ 
    NSLog(@"within ExecuteQuery:WithAction: Query is: %@ and Action is: %@",query,doAction); 
    NSString *returnResult; 
    @try { 

     NSString *returnResult; 
     NSMutableURLRequest *postRequest; 
     NSError *error; 
     NSData *searchData; 
     NSHTTPURLResponse *response; 
     postRequest=[self directMySQLQuery:query WithAction:doAction]; // this method sends actual POST request 

     NSLog(@"after directMYSQL in QueryByPost- performQuery... ErrorLogMsg"); 
     searchData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&error]; 
     returnResult = [[NSString alloc] initWithData:searchData encoding:NSASCIIStringEncoding]; 

     NSString *resultToBeCompared=[returnResult stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
     NSLog(@"result obtained - %@/ resultToBeCompared - %@",returnResult,resultToBeCompared); 


     if(![resultToBeCompared isEqualToString:@""]){ 
     }else { 
      sleep(10); 
      postRequest=[self directMySQLQuery:query WithAction:doAction]; 
      searchData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&error]; 
      if(![resultToBeCompared isEqualToString:@""]){ 
      }else { 
       sleep(10); 
       postRequest=[self directMySQLQuery:query WithAction:doAction]; 
       searchData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&error]; 
       if(![resultToBeCompared isEqualToString:@""]){ 
       }else { 
        sleep(10); 
        postRequest=[self directMySQLQuery:query WithAction:doAction]; 
        searchData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&error]; 
        if(![resultToBeCompared isEqualToString:@""]){ 
        }else { 
         sleep(10); 
         postRequest=[self directMySQLQuery:query WithAction:doAction]; 
         searchData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&error]; 
         if(![resultToBeCompared isEqualToString:@""]){ 
         }else { 
          return nil; 
         } 
        } 
       } 
      } 
     } 




     returnResult = [[NSString alloc] initWithData:searchData encoding:NSASCIIStringEncoding]; 

     return searchData; 
    } 
    @catch (NSException * e) { 
     NSLog(@"within QueryByPost , execurteQuery:WithAction - %@",[e description]); 
     return nil;  
    } 
} 

// The method which sends POST request to server , is of following form: 
-(NSMutableURLRequest *)directMySQLQuery:(NSString*)query WithAction:(NSString*)doAction{ 
    @try{ 
     NSLog(@"Query is: %@ and Action is: %@",query,doAction); 

     // some pre initialization 
     NSString *stringBoundary,*contentType; 
     NSURL *cgiUrl ; 
     NSMutableURLRequest *postRequest; 
     NSMutableData *postBody; 
     NSString *[email protected]"434"; 

     cgiUrl = [NSURL URLWithString:@"http://keysoftwareservices.com/API.php"]; 
     postRequest = [NSMutableURLRequest requestWithURL:cgiUrl]; 
     [postRequest setHTTPMethod:@"POST"]; 

     stringBoundary = [NSString stringWithString:@"0000ABCQueryxxxxxx"]; 
     contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", stringBoundary]; 
     [postRequest addValue:contentType forHTTPHeaderField: @"Content-Type"]; 

     //setting up the body: 
     postBody = [NSMutableData data]; 
     [postBody appendData:[[NSString stringWithFormat:@"\r\n\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"code\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:ans] dataUsingEncoding:NSUTF8StringEncoding]]; 

     [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"action\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:doAction] dataUsingEncoding:NSUTF8StringEncoding]]; 

     [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"devmode\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"devmode"]] dataUsingEncoding:NSUTF8StringEncoding]]; 

     [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"q\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postBody appendData:[[NSString stringWithString:query] dataUsingEncoding:NSUTF8StringEncoding]]; 

     [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [postRequest setHTTPBody:postBody]; 

     NSLog(@"Direct My SQL ok");// Some time application crashes afte this log 

     //Some time application crashes after "Direct My SQL ok" log 
     return [postRequest mutableCopy]; 

    }@catch (NSException * e) { 
     NSLog(@"NSException %@",e); 
     NSRunAlertPanel(@"Error Panel", @"Within QueryByPost- directMySQLQuery...%@", @"OK", nil, nil,e); 
     return nil; 
    } 
} 

+1

标志着我最你的问题的身体作为代码,试图使它的可读性。 – bbum 2009-09-24 05:46:55

回答

1

EXC_BAD_ACCESS是一个严重的错误。这不是一个例外,你不能抓住它。

这意味着你的代码已经做了一些试图访问无效的内存。最有可能的是,试图取消引用被删除的指针。过度发布是实现这种崩溃的常用方法。

在这种情况下,因为你是在用户界面对象从后台线程击败崩溃的原因是最有可能的。没有什么是线程安全的,除非文档明确指出它是线程安全的,即使如此,对于线程可以做什么也可能有限制。

鉴于缺乏适当的线程模型的死亡,我没有非常密切的代码的其他人看起来。但是,内存管理存在一些明显的问题。泄漏和可能的过度释放或两个​​。

我的建议是完全重写这段代码。首先考虑如何沿着模型 - 视图 - 控制器[MVC]行解决问题。考虑是否可以使用NSURL *和NSHTTP *类来进行客户端/服务器通信 - 如果可以的话,可以将它们配置为异步通信。

至于线程而言,你需要非常仔细地考虑如何划分的问题了;如何在主线程不执行线程不安全动作的同时移动主线程的位。

+0

我们的应用程序通常在没有任何错误的变量值的最后一个日志记录之后崩溃。我在一个定时器中调用这些函数(每25秒后)。崩溃自发地发生,即。它可能会在1小时后崩溃或在15分钟后崩溃。如果我们使用断点调试,应用程序每25秒:( 注册后停止:异步通信,为此,我们不得不使用NSURLConnection的 的委托方法,但我们需要它的代码 下位输出,因为我们需要的NSData从回报该功能.. 是否有通过它我们可以执行的代码下位后,与会代表呼吁 – 2009-09-24 08:05:29

+1

不能说这足够强烈的任何方法:停止试图解决症状和解决问题这个代码,正如所写的,是错误的;数十个错误,但更重要的是,结构是有缺陷的。在解决这个问题之前,你需要退一步了解如何正确地构建Cocoa应用程序。 – bbum 2009-09-24 17:13:53

相关问题