2009-09-24 30 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

相關問題