私は、次の.xmlファイルを持っている:NSXMLParserは、最後のノード(可能なメモリの問題)を解析しません
<?xml version="1.0" encoding="UTF-8"?>
<company>
<employee>
<id>0</id>
<firstname>Jack</firstname>
<lastname>Johnson</lastname>
<jobtitle>CEO</jobtitle>
<departmentid>0</departmentid>
<parentid>0</parentid>
</employee>
<employee>
<id>1</id>
<firstname>Mik</firstname>
<lastname>Black</lastname>
<jobtitle>Senior Manager</jobtitle>
<departmentid>0</departmentid>
<parentid>0</parentid>
</employee>
<employee>
<id>2</id>
<firstname>Kim<firstname>
<lastname>Friht</lastname>
<jobtitle>Senior Manager</jobtitle>
<departmentid>0</departmentid>
<parentid>0</parentid>
</employee>
...
次のヘッダーファイル:
#import <Foundation/Foundation.h>
#import "Employee.h"
@interface IdParser : NSObject <NSXMLParserDelegate> {
NSXMLParser *xmlParser;
NSMutableArray *employees;
NSString *currentElement;
Employee *employee;
NSMutableString *tempId, *tempFirstName, *tempLastName, *tempDeptId, *tempJobTitle, *tempParentId;
}
-(NSMutableArray *)getSubordinates:(int)idNumber;
@end
そして、次の実装:
#import "IdParser.h"
#import "Employee.h"
@implementation IdParser
- (void)start{
NSString *file = @"https://stackoverflow.com/users/localadmin/Desktop/employeeData.xml";
NSFileManager *filemgr = [NSFileManager defaultManager];
NSData *dataBuffer = [filemgr contentsAtPath: file];
xmlParser = [[NSXMLParser alloc] initWithData:dataBuffer];
[xmlParser setDelegate:self];
[xmlParser parse];
}
- (void) parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict{
[currentElement release];
currentElement = [elementName copy];
if([elementName isEqualToString:@"employee"]){
employee = [[Employee alloc]init];
}
if([elementName isEqualToString:@"id"]){
tempId = [[NSMutableString alloc]init ];
}
if([elementName isEqualToString:@"firstname"]){
tempFirstName = [[NSMutableString alloc]init ];
}
if([elementName isEqualToString:@"lastname"]){
tempLastName = [[NSMutableString alloc]init ];
}
if([elementName isEqualToString:@"jobtitle"]){
tempJobTitle = [[NSMutableString alloc]init ];
}
if([elementName isEqualToString:@"departmentid"]){
tempDeptId = [[NSMutableString alloc]init ];
}
if([elementName isEqualToString:@"parentid"]){
tempParentId = [[NSMutableString alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser
foundCharacters:(NSString *)string{
if([currentElement isEqualToString:@"id"]){
[tempId appendString:string];
}
if([currentElement isEqualToString:@"firstname"]){
[tempFirstName appendString:string];
}
if([currentElement isEqualToString:@"lastname"]){
[tempLastName appendString:string];
}
if([currentElement isEqualToString:@"jobtitle"]){
[tempJobTitle appendString:string];
}
if([currentElement isEqualToString:@"departmentid"]){
[tempDeptId appendString:string];
}
if([currentElement isEqualToString:@"parentid"]){
[tempParentId appendString:string];
}
}
-(void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName{
if([elementName isEqualToString:@"employee"]){
[employee setIdNumber:[tempId intValue]];
[tempId release];
[employee setFirstName:tempFirstName];
[tempFirstName release];
[employee setLastName:tempLastName];
[tempLastName release];
[employee setJobTitle:tempJobTitle];
[tempJobTitle release];
[employee setDepartmentIdNumber:[tempDeptId intValue]];
[tempDeptId release];
[employee setParentIdNumber:[tempParentId intValue]];
[tempParentId release]; //IF I REMOVE THIS LINE, THE PROGRAM DOES NOT CRASH
[employees addObject:employee];
[employee release];
}
}
@end
非常に奇妙な問題が発生しています。 IdParserに実装されているstartメソッドを呼び出すときは、すべてを解析しますが、XMLの最後のノード(parentid)に到達すると、何か不思議なことが起こります。
プログラムが終了し、私は次のエラーメッセージが表示されます。
malloc関数:*オブジェクト0x4b33360のエラー:解放されたオブジェクトの不正なチェックサム - オブジェクトはおそらく、解放された後に変更されました。 *は、デバッグするためにmalloc_error_breakにブレークポイントを設定しました 現在の言語:auto;現在、Objective-Cの 今プログラムで使用可能なメモリがありません:私は[tempParentId release];
行を削除すると、安全でないが、不思議なことにmalloc
を呼び出すために、プログラムは正常に動作します。私はXMLの要素を再配置しようとしましたが、同じことがもう一度起こります。プログラムは最後の要素でクラッシュします。 Objective-CやiOSの新機能で、何が問題の原因になっているのかは分かりませんので、私は助けを求めています。私は上記の行を削除した後にプログラムが正常に動作するため、どこかにメモリの問題があると思います。
ありがとうございました。
ペタル
EDIT:
私は私がobj-Cに新しいですし、私は学ぶために、この例を使用していますので、私はメモリ管理とそれに接続されたすべての事についてあまり理解していない言ったようにそれについて私の知識を広げてください。それは、あなたがそれを修正する方法を提案する前に説明されたエラーの原因を正確に説明しようとすることができます。
EDIT2:
時々私が代わりに私が上記のエラーメッセージのコードを、実行すると、プログラムがフリーズし、コンソールに私は以下を参照してください
現在の言語:自動;現在objective-c (gdb)
これは、私がランダムな動作を経験しているため、問題の原因となる可能性があります。
EDIT3:
Employeeクラス:
#import <Foundation/Foundation.h>
@interface Employee : NSObject {
int idNumber;
NSString *firstName;
NSString *lastName;
int departmentIdNumber;
NSString *jobTitle;
int parentIdNumber;
}
-(id)initWithIdNumber:(int)idValue
firstName:(NSString *)firstNameValue
lastName:(NSString *)lastNameValue
departmentIdNumber:(int)departmentIdNumberValue
jobTitle:(NSString *)jobTitleValue
parentIdNumber:(int)parentIdNumberValue;
@property(nonatomic) int idNumber;
@property(nonatomic, retain) NSString *firstName;
@property(nonatomic, retain) NSString *lastName;
@property(nonatomic, retain) NSString *jobTitle;
@property(nonatomic) int departmentIdNumber;
@property(nonatomic) int parentIdNumber;
@end
#import "Employee.h"
@implementation Employee
@synthesize idNumber, firstName, lastName, departmentIdNumber, jobTitle, parentIdNumber;
-(id)initWithIdNumber:(int)idValue
firstName:(NSString *)firstNameValue
lastName:(NSString *)lastNameValue
departmentIdNumber:(int)departmentIdNumberValue
jobTitle:(NSString *)jobTitleValue
parentIdNumber:(int)parentIdNumberValue{
self = [super init];
if(self){
[self setIdNumber:idValue];
[self setFirstName:firstNameValue];
[self setLastName:lastNameValue];
[self setDepartmentIdNumber:departmentIdNumberValue];
[self setJobTitle:jobTitleValue];
[self setParentIdNumber:parentIdNumberValue];
}
return self;
}
-(NSString *) description{
NSString *desc = [[NSString alloc]initWithFormat:@"ID: %d, firstname: %@, lastname: %@, departmentID: %d, jobtitle: %@, parentID: %d", idNumber, firstName, lastName, departmentIdNumber, jobTitle, parentIdNumber];
return desc;
}
@end
あなたのコードはすべてですか?他の場所で 'tempParentId'を使って何もしていないと確信していますか? –
それはすべてのコードです。 tempParentIdはヘッダーファイルで定義され、実装ファイルでアクセスされます。私はそれらを完全にコピーしました。おかげで – Petar
長いショットのビットが、それを解放した直後に 'tempParentId'を' nil'に設定しようとしました。私はあなたのコードでそれがなぜ必要なのかわかりませんが、それは良い習慣と考えられています。 –