仪器中有内存泄漏的类
我有几个类,其中的函数是针对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
这绝对是一个越野车类,因为漏水,每次访问都是泄漏:(
任何帮助吗?
这里有一些事情我注意到:
- [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对象。请记住,当你泄漏一个对象时,你也会泄漏这些对象持有的引用。即使这些类是无漏洞的,如果实例化这些类的代码没有正确地释放对象,您也会看到这些类中的所有成员都泄漏了。修复泄漏时,请务必首先查找“顶层”对象。
感谢您的回应。这意味着每次我声明一个iSQLResult对象并将其分配给[iSQL getSQLR]的返回时,签名对象也必须被释放?谢谢。 – NemeSys 2012-03-01 09:25:21
是的, - [iSQL getSQLR]中的复制方法返回带有+1保留计数的对象。为了避免泄漏,你需要释放当调用范围完成或更改代码返回[[SQLR copy] autorelease]。 – davehayden 2012-03-01 22:18:14
Woa。这是大量的代码,要求在互联网上的随机无偿人员查找内存管理错误。如果您需要帮助,请将其缩小为小部分,并指定具体错误。 – Almo 2012-02-29 21:50:54
你运行过分析仪吗? – 2012-02-29 21:53:38
看起来你永远不会在SQLExec中释放分配给SQLR的第二个值。 (请学习标准C语言大写惯例,让您的代码更易于其他人使用。) – 2012-02-29 22:00:14