I have the following .xml file :
<?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>
...
The following header file:
#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
And the following implementation:
#import "IdParser.h"
#import "Employee.h"
@implementation IdParser
- (void)start{
NSString *file = @"/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
I am experiencing a very strange problem with it. When I am to call the start method implemented in IdParser, it parses everything but when it gets to the last node of the XML (parentid), something strange happens.
The program quits and I receive the following error message:
malloc: * error for object 0x4b33360: incorrect checksum for freed object - object was probably modified after being freed. * set a breakpoint in malloc_error_break to debug Current language: auto; currently objective-c No memory available to program now: unsafe to call malloc
Strangely, when I remove the [tempParentId release]; line, the program runs fine. I have tried rearranging the elements in the XML and the same thing happens again: the program crashes at the last element. It does no make sense to me what is causing the problem as I am new to Objective-C and iOS so I am asking for help. I guess there is a memory problem somewhere because the program runs fine after I remove the line that I mentioned above.
Thanks for any help.
Petar
EDIT:
As I said I am new to Obj-C and I don't understand much about memory management and all the things connected with it so I am using this example to learn and expand my knowledge about it. That said, can you please try to explain what exactly is causing the error described before suggesting how to fix it.
EDIT2:
Sometimes when I run the code, instead of the error message which I described above, the program freezes and in the console I see just:
Current language: auto; currently objective-c (gdb)
This may be a clue as to what the problem is because I am experiencing random behaviour.
EDIT3:
Employee class:
#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
tempParentIdelsewhere?tempParentIdtonilimmediately after releasing it. I can't see why that would be necessary in your code, but it's considered a good practice.nilto prevent anything from trying to use it. But if setting it tonilfixed the problem then here must be some serious bug somewhere in your code (I don't see any in what you've posted) and you should try to find it. The bug may or may not be a memory management issue... Objective-C is a low level language, and you're dealing with pointers. So the bug could be almost anywhere in your app. That's why I turn ARC on, so I never have headaches like these. You should set the others tonil.