2012-02-29 89 views
0

我有幾個類,其中的函數是針對WEB服務執行SQL語句以獲取或設置數據庫中的數據。儀器中有內存泄漏的類

工作正常,但問題是當我在儀器/泄漏測試中90%的泄漏是因爲這些類。

你能告訴我我在丟什麼嗎?

謝謝。

下面是代碼:

在數據存儲:

.H

@interface iSQLResult : NSObject { 
    NSMutableArray *Records; 
} 
@property (nonatomic, assign) int CountX; 
@property (nonatomic, assign) int CountY; 
@property (nonatomic, retain) NSMutableArray *Columns; 
@property (nonatomic, retain) NSMutableArray *Records; 
@property (nonatomic, retain) NSMutableArray *FieldsNames; 
@property (nonatomic, assign) int ErrorCode; 
@property (nonatomic, retain) NSString *ErrorDescription; 


-(void)addField:(NSString*)fieldName; 
-(void)addRecord:(NSMutableArray*)items; 
-(NSMutableArray *)getRecord:(int)y; 
-(NSString*)getValue:(int) x posY:(int) y; 
-(NSString*)getValueByName:(NSString *) colName posY:(int) y; 
-(void)setValueByName:(NSString *) colName posY:(int) y value:(NSString *)value; 
-(id) copyWithZone: (NSZone *) zone; 
@end 

.M

#import "iSQLResult.h" 
#import <stdarg.h> 

@implementation iSQLResult 
@synthesize CountX; 
@synthesize CountY; 
@synthesize Columns; 
@synthesize Records; 
@synthesize FieldsNames; 
@synthesize ErrorCode; 
@synthesize ErrorDescription; 

-(id)init 
{ 
    self = [super init]; 

    if (self) 
    { 
     self.CountX =0; 
     self.CountY =0; 
     self.ErrorCode = 0; 
     self.ErrorDescription = @""; 

     self.FieldsNames = [NSMutableArray array]; 
     self.Columns = [NSMutableArray array]; 
     self.Records = [NSMutableArray array]; 

    } 

    return self; 
} 
-(void)removeRecord:(int)index 
{ 
    [self.Records removeObjectAtIndex:index]; 
    self.CountY = self.CountY - 1; 
} 
-(void)addField:(NSString*)fieldName 
{ 
    [self.FieldsNames addObject:[NSString stringWithFormat:@"%@", fieldName]]; 
    self.CountX = self.CountX +1; 
} 
-(void)addRecord:(NSMutableArray*)items 
{ 
    [self.Records addObject:items]; 
    self.CountY = self.CountY +1; 
} 
-(NSMutableArray *)getRecord:(int)y 
{ 
    return [Records objectAtIndex:y]; 
} 
-(NSString *)getValue:(int) x posY:(int)y 
{ 
    return [[NSString stringWithFormat:@"%@", [[Records objectAtIndex:y] objectAtIndex:x]] copy]; 
} 
-(NSString*)getValueByName:(NSString *) colName posY:(int) y 
{ 
    int a=0; 
    for (a=0;a<CountX;a++) 
    { 
     if ([[colName uppercaseString] isEqualToString:[[FieldsNames objectAtIndex:a] uppercaseString]]) 
     { 
      return [[NSString stringWithFormat:@"%@", [[Records objectAtIndex:y] objectAtIndex:a]] copy]; 
     } 
    } 
    return @""; 
} 
-(void)setValueByName:(NSString *) colName posY:(int) y value:(NSString *)value 
{ 
    int a=0; 
    for (a=0;a<CountX;a++) 
    { 
     if ([[colName uppercaseString] isEqualToString:[[FieldsNames objectAtIndex:a] uppercaseString]]) 
     { 
      [[Records objectAtIndex:y] replaceObjectAtIndex:a withObject:value]; 
     } 
    } 

} 
-(void)dealloc 
{ 
    [Columns release]; 
    [Records release]; 
    [FieldsNames release]; 
    [ErrorDescription release]; 

    [super dealloc]; 
} 
-(id) copyWithZone: (NSZone *) zone 
{ 
    iSQLResult *SQLRCopy = [[iSQLResult allocWithZone: zone] init]; 

    [SQLRCopy setCountX:self.CountX]; 
    [SQLRCopy setCountY:self.CountY]; 
    [SQLRCopy setRecords:[self.Records mutableCopyWithZone:zone]]; 
    [SQLRCopy setColumns:[self.Columns mutableCopyWithZone:zone]]; 
    [SQLRCopy setFieldsNames:[self.FieldsNames mutableCopyWithZone:zone]]; 
    [SQLRCopy setErrorCode:self.ErrorCode]; 
    [SQLRCopy setErrorDescription:[self.ErrorDescription copyWithZone:zone]]; 

    return SQLRCopy; 
} 
@end 

類誰索要數據到web服務通信類,並獲得xml結構:

.H

#import <Foundation/Foundation.h> 
#import "iSQLResult.h" 
#import "IM2_WebServiceComm.h" 

@interface iSQL : NSObject <NSXMLParserDelegate> { 

    iSQLResult *SQLR; 
    IM2_WebServiceComm * WSC; 

    NSXMLParser *xmlParser; 
    BOOL Found; 
    BOOL FieldsReaded; 
    BOOL loadFieldsNow; 
    BOOL loadErrNumNow; 
    BOOL loadErrDesNow; 
    NSString *chunksString; 
    NSMutableArray *tempRecord; 
} 
@property (nonatomic, retain) NSString *URLConnection; 
-(void)SQLReader:(NSString*)SQLString; 
-(void)SQLExec:(NSString*)SQLString; 
-(void)setURLConnection:(NSString *) WebSURL; 
-(iSQLResult*) getSQLR; 
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName; 
-(void) parser:(NSXMLParser *) parser foundCharacters:(NSString *)string; 
-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *) attributeDict; 
@end 

.M

#import "iSQL.h" 
@implementation iSQL 
@synthesize URLConnection; 
- (iSQLResult*)getSQLR 
{ 
    return [SQLR copy]; 
} 
-(void)SQLExec:(NSString*)SQLString 
{ 

    FieldsReaded = NO; 
    Found = NO; 
    loadFieldsNow = NO; 

    if (SQLR) 
    { 
     [SQLR release]; 
     SQLR = nil; 
    } 


SQLR = [[iSQLResult alloc] init]; 

WSC = [[IM2_WebServiceComm alloc] init]; 
[WSC setURL:URLConnection]; 

NSString *theXML = [WSC callMethod:@"ExecNonQuery" sendInstruction:SQLString]; 

@try 
{ 
    xmlParser = [[NSXMLParser alloc] initWithData:[theXML dataUsingEncoding:NSUTF8StringEncoding]]; 
    [xmlParser setDelegate: self]; 
    [xmlParser setShouldResolveExternalEntities:NO]; 
    if(![xmlParser parse]) 
    { 
     NSLog(@"ERROR PARSING"); 
    } 
    [xmlParser release]; 
} 
@catch(NSException * ex) 
{ 
    NSLog(@"%@",[[ex reason] UTF8String]); 
} 
[WSC release]; 
} 
-(void)SQLReader:(NSString*)SQLString 
{ 

FieldsReaded = NO; 
Found = NO; 
loadFieldsNow = NO; 

if (SQLR) 
{ 
    [SQLR release]; 
    SQLR = nil; 
} 

SQLR = [[iSQLResult alloc] init]; 

WSC = [[IM2_WebServiceComm alloc] init]; 
[WSC setURL:URLConnection]; 

NSString *theXML = [WSC callMethod:@"ExecSQL" sendInstruction:SQLString]; 

@try 
{ 
    xmlParser = [[NSXMLParser alloc] initWithData:[theXML dataUsingEncoding:NSUTF8StringEncoding]]; 
    [xmlParser setDelegate: self]; 
    [xmlParser setShouldResolveExternalEntities:NO]; 
    if(![xmlParser parse]) 
    { 
     NSLog(@"ERROR PARSING"); 
    } 
    [xmlParser release]; 
} 
@catch(NSException * ex) 
{ 
    NSLog([NSString stringWithFormat:@"%@",[[ex reason] UTF8String]]); 
} 
[WSC release]; 
} 

-(iSQLResult *)getSingleSQLR:(iSQLResult *)SQLSource usingRow:(int)y 
{ 

iSQLResult *SQLRAux = [[[iSQLResult alloc]init]retain]; 

[SQLRAux setCountX:SQLSource.CountX]; 
[SQLRAux addRecord:[SQLSource getRecord:y]]; 
[SQLRAux setFieldsNames:SQLSource.FieldsNames]; 

return SQLRAux; 

} 

-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{ 
    NSLog(@"Error on XML Parse: %@", [parseError localizedDescription]); 
} 

//#pragma XML Parser Delegate Methods 
-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *) attributeDict 
{ 
    if (!chunksString) 
{ 
    chunksString = [[NSString alloc] init]; 
} 
chunksString = @""; 
if ([elementName isEqualToString:@"ErrCode"]) 
{ 
    loadErrNumNow = YES; 
} 
if ([elementName isEqualToString:@"ErrDesc"]) 
{ 
    loadErrDesNow = YES; 
} 

if ([elementName isEqualToString:@"Table"]) 
{ 
    Found = YES; 
    loadFieldsNow = NO; 
    tempRecord = [[NSMutableArray alloc] init]; 
} 

if (Found && ![elementName isEqualToString:@"Table"]) 
{ 
    loadFieldsNow = YES; 
    if (!FieldsReaded) 
    { 
     [SQLR addField:elementName]; 
    } 
} 
} 

-(void) parser:(NSXMLParser *) parser foundCharacters:(NSString *)string 
{ 
    chunksString = [chunksString stringByAppendingString:string]; 
}  

-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
NSString * finalString; 
finalString = [NSString stringWithFormat:@"%@",chunksString]; 

if (loadErrNumNow) 
{ 
    [SQLR setErrorCode:[finalString intValue] ]; 
    loadErrNumNow = NO; 
} 
if (loadErrDesNow) 
{ 
    [SQLR setErrorDescription:finalString]; 
    loadErrDesNow = NO; 
}   

if (Found) 
{ 
    if (loadFieldsNow) 
    { 
     [tempRecord addObject:finalString]; 
    } 
} 

if ([elementName isEqualToString:@"Table"]) 
{ 
    [SQLR addRecord:tempRecord]; 
    [tempRecord release]; 
    Found = NO; 
    FieldsReaded = YES; 
    loadFieldsNow = NO; 

} 
} 

-(void)dealloc 
{ 
    if (SQLR) 
    { 
     [SQLR release]; 
     SQLR = nil; 
    } 

    [URLConnection release]; 

    [super dealloc]; 

} 
@end 

這絕對是一個越野車類,因爲漏水,每次訪問都是泄漏:(

任何幫助嗎?

+1

Woa。這是大量的代碼,要求在互聯網上的隨機無償人員查找內存管理錯誤。如果您需要幫助,請將其縮小爲小部分,並指定具體錯誤。 – Almo 2012-02-29 21:50:54

+0

你運行過分析儀嗎? – 2012-02-29 21:53:38

+0

看起來你永遠不會在SQLExec中釋放分配給SQLR的第二個值。 (請學習標準C語言大寫慣例,讓您的代碼更易於其他人使用。) – 2012-02-29 22:00:14

回答

2

這裏有一些事情我注意到:

- [iSQLResult copyWithZone:]

你發送mutableCopyWithZone的結果:(返回保留的對象)的制定者,它保留了再次對象。要解決這個問題的一種方式是自動釋放的副本:

[SQLRCopy setRecords:[[self.Records mutableCopyWithZone:zone] autorelease]] 

- [Interactive SQL SQLEXEC:]和 - [Interactive SQL SQLReader的:]

實例變量WSC和xmlPareser被alloced然後釋放,但沒有設置爲零。這不是泄漏,但是您保留對已發佈對象的引用。如果你解除這一點,你會崩潰。

- [Interactive SQL getSingleSQLR:usingRow:]

iSQLResult *SQLRAux = [[[iSQLResult alloc]init]retain]; 

您的意思是自動釋放,而不是保留在那裏? (如果你沒有,你不應該也自動釋放在getSQLR回報,一致性?)

- [Interactive SQL解析器:didStartElement:的namespaceURI:qualifiedName中:屬性:]

chunksString是alloced(+ 1保留),但後來在解析器:foundCharacters:你失去了引用(即泄漏字符串)並用自動釋放字符串替換它。


這就是我注意到的一切。這聽起來像你泄漏的不僅僅是這些對象,所以我猜你也在泄漏iSQL和/或iSQLResult對象。請記住,當你泄漏一個對象時,你也會泄漏這些對象持有的引用。即使這些類是無漏洞的,如果實例化這些類的代碼沒有正確地釋放對象,您也會看到這些類中的所有成員都泄漏了。修復泄漏時,請務必首先查找「頂層」對象。

+0

感謝您的迴應。這意味着每次我聲明一個iSQLResult對象並將其分配給[iSQL getSQLR]的返回時,簽名對象也必須被釋放?謝謝。 – NemeSys 2012-03-01 09:25:21

+0

是的, - [iSQL getSQLR]中的複製方法返回帶有+1保留計數的對象。爲了避免泄漏,你需要釋放當調用範圍完成或更改代碼返回[[SQLR copy] autorelease]。 – davehayden 2012-03-01 22:18:14