getting a memory SIGBUS error when adding a custom object to a mutableArray in objective c.
#interface stak : NSObject {
NSString *idval,
*username,
*userid,
*password,
*snippet,
*curStakId,
*pageCount,
*memberCount,
*imgURL,
*tags;
UIImage *icon;
}
#property (nonatomic,retain) NSString *idval,*username,*userid,*password,*curStakId,*snippet,*pageCount,*memberCount,*imgURL,*tags;
#property (nonatomic,retain) UIImage *icon;
-(id)initWithidval:(NSString *)idvalue
username:(NSString *)user
userid:(NSString *)uid
password:(NSString *)pass
curStakId:(NSString *)stakid
snippet:(NSString *)snip
pageCount:(NSString *)page
memberCount:(NSString *)members
tags:(NSString *)tag_vals
imgURL:(NSString *)img
icon:(UIImage *)iconImg;
#end
and the .m
#implementation stak
#synthesize idval;
#synthesize username;
#synthesize userid;
#synthesize password;
#synthesize curStakId;
#synthesize snippet;
#synthesize pageCount;
#synthesize memberCount;
#synthesize imgURL;
#synthesize icon;
#synthesize tags;
-(id)initWithidval:(NSString *)idvalue
username:(NSString *)u
userid:(NSString *)uid
password:(NSString *)p
curStakId:(NSString *)stakid
snippet:(NSString *)snip
pageCount:(NSString *)page
memberCount:(NSString *)members
tags:(NSString *)tag_vals
imgURL:(NSString *)img
icon:(UIImage *)iconImg{
if (self = [super init]) {
[self setIdval:idvalue];
[self setUsername:u];
[self setUserid:uid];
[self setPassword:p];
[self setCurStakId:stakid];
[self setSnippet:snip];
[self setPageCount:page];
[self setMemberCount:members];
[self setTags:tag_vals];
[self setImgURL:img];
[self setIcon:iconImg];
}
return self;
}
-(void)dealloc{
[idval release];
[username release];
[userid release];
[snippet release];
[imgURL release];
[icon release];
[tags release];
[curStakId release];
[memberCount release];
[password release];
[super dealloc];
}
#end
and this is where it is called and released.
NSMutableArray *_return_staks = [[NSMutableArray alloc]init];
stak *_stakItem = [[stak alloc]initWithidval:[NSString stringWithFormat:#"%#",[staks objectAtIndex:i]]
username:[NSString stringWithFormat:#"%#",[creators objectAtIndex:i]]
userid:[NSString stringWithFormat:#"%#",[creatorid objectAtIndex:i]]
password:[NSString stringWithFormat:#"%#",[privacy objectAtIndex:i]]
curStakId:[NSString stringWithFormat:#"%#",[idvals objectAtIndex:i]]
snippet:tempString
pageCount:tempPcount
memberCount:tempMcount
tags:[NSString stringWithFormat:#"%#",[tags objectAtIndex:i]]
imgURL:[NSString stringWithFormat:#"%#",[img objectAtIndex:i]]
icon:nil];
[_return_staks addObject:_stakItem];
[_stakItem release];
When i go to reference the stored item i get a SIGBUS error, however when i remove the "[_stakItem release]" it works fine, however this creates a leak. Is there any way to correct this?
It's difficult to give you a definitive answer without seeing the context of the actual crash, but you are probably over releasing _stackItem somewhere. This is probably caused by keeping a reference to it but releasing the array which is the only thing that owns it. There is actually nothing wrong with the code you have posted (well, your string properties should really be copy properties, but that is not what is causing your crash).
Are you using _stakItem after the release?
Do you have a sequence like:
stak* foo = [_return_staks objectAtIndex: fooIndex];
// etc
[_return_staks release];
// etc
[foo doSomething]; // Likely to have gone away by now.
Related
I have the Header of this class in my project:
#interface VideoItem : NSObject <NSCoding> {
NSString *idStr;
NSString *name;
NSString *link;
}
-(id)initWithVideoItem:(VideoItem*)video;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *link;
#property (nonatomic, retain) NSString *idStr;
#end
this is the implement:
#implementation VideoItem
#synthesize name,link,idStr;
-(id)initWithVideoItem:(VideoItem*)video{
if (self = [super init]) {
self.name = video.name;
self.link = video.link;
self.idStr = video.idStr;
}
return self;
}
#pragma mark
#pragma mark NSCoder
- (void)encodeWithCoder:(NSCoder *)encoder{
[encoder encodeObject:self.name forKey:#"video_name"];
[encoder encodeObject:self.link forKey:#"video_link"];
[encoder encodeObject:self.idStr forKey:#"video_id"];
[encoder encodeObject:self.imgUrl forKey:#"video_img"];
[encoder encodeObject:self.viewCount forKey:#"video_views"];
[encoder encodeObject:self.artist forKey:#"video_artist"];
[encoder encodeObject:self.timeStr forKey:#"video_timestr"];
[encoder encodeInt:self.seconds forKey:#"video_secondes"];
[encoder encodeInt:self.rating forKey:#"video_rating"];
[encoder encodeObject:self.pubDate forKey:#"pubDate"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if(self = [super init]){
self.name = [decoder decodeObjectForKey:#"video_name"];
self.link = [decoder decodeObjectForKey:#"video_link"];
self.idStr = [decoder decodeObjectForKey:#"video_id"];
}
return self;
}
#end
And i want to know if in case like this i need to add dealloc method and release the strings or not?
Yes you should release the strings because when using the properties that retain objects.
- (void)dealloc {
[idStr release];
[name release];
[link release];
[super dealloc];
}
Normally you would copy the object in the init, this is a better way then since the orginal object can then savely be edited or released.
-(id)initWithVideoItem:(VideoItem*)video{
if ((self = [super init])) {
name = [video.name copy];
link = [video.link copy];
idStr = [video.idStr copy];
}
return self;
}
Since the copy method return a retained object you want to skip the property, since that would increase the retain count.
On a other note: the objective-c convention the private ivar should start with an _ to make it more obvious that they are not properties.
Use ARC and forget any problems related to memory management.
Even apple encourages using ARC whenever possible. If you are doing this as a new development, I would recommend you to use ARC.
In case you do not want to use ARC, you need to implement dealloc and release your member variables.
Use this, release all your allocated variables and at last call super dealloc :
- (void)dealloc{
[idStr release];
[name release];
[link release];
[super dealloc];
}
you have to write
- (void)dealloc
Method as you are retaining the variable's. and release these variables in this method.
You are retaining your string properties.
So it's your task to release it.
So add a dealloc method and release them.
- (void)dealloc
{
[idStr release];
[name release];
[link release];
[super dealloc];
}
In fact you need not call the release on the ivars. Instead use the properties
self.ivar = nil. This releases your memory and sets the pointes to nil as a result of it there are no dangling pointers.
if you use [ivar release], ivar is released but is a dangling pointer, so most of the time ivar = nil; is done after releasing the ivar.
- (void)dealloc
{
self.idStr = nil;
self.name = nil;
self.link = nil;
[super dealloc];
}
I have declared NSString with some string value in ViewdidLoad like..
int i=1;
strval=[NSString stringWithFormat:#"%03d",i];
strval=[NSString stringWithFormat:#"S%#",strval];
NSLog(#"Value %#",strval);
it gives correct result as S001, but when i print this same in IBAction like,
- (IBAction)stringvalue:(id)sender {
NSLog(#"Value %#",strval);
}
it gives unknown values each time.Sometimes it throws EXEC_BAD_ACCESS error.
Please help me..
Try something like this
in .h
#property (nonatomic, strong) NSString *strval;
in .m
#synthesize strval = _strval
- (void)viewDidLoad
{
int i = 4;
// ARC
_strval = [NSString stringWithFormat:#"hello %d", i];
// None ARC
// strcal = [[NSString alloc] initwithFormat:#"hello %d",i];
NSLog(#"%#", _strval);
// Prints "hello 4" in console (TESTED)
}
- (IBAction)buttonPress:(id)sender
{
NSLog(#"%#", _strval);
// Prints "hello 4" in console (TESTED)
}
using ARC. This has been tested and works the way the question has been asked.
Looks like you aren't using ARC, so the string is being released the next time the autorelease pool drains. You need to explicitly retain it in viewDidLoad and explicitly release it in your overwridden dealloc method:
- (void)viewDidLoad
{
...
strval = [[NSString stringWithFormat:#"%03d", i] retain];
....
}
- (void)dealloc
{
[strval release];
...
[super dealloc];
}
(I am assuming you've actually declared strval as an instance method).
in .h
#property (nonatomic, strong) NSString *strval;
in .m
#synthesize strval = _strval
- (void)viewDidLoad
{
...
self.strval = [NSString stringWithFormat:#"%03d", i];
....
}
- (void)dealloc
{
self.strval = nil;
...
[super dealloc];
}
This one works either, with ARC and without.
Just one addition: With ARC the statement [super dealloc]; must be omitted.
My NSManagedObject says Tag has 2 To-many relationships,says posts and children. And I let Xcode 4 to generate NSManagedObject subclass for it. But I find that only one relationship can return the correct class information.
So the codes are look like following and even these codes were generated by xcode, you can immediately find something wrong,
#interface Tag : NSManagedObject {
#private
}
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSSet* children;
#property (nonatomic, retain) NSSet* posts;
#end
...
- (void)addChildrenObject:(NSManagedObject *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:#"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:#"children"] addObject:value];
[self didChangeValueForKey:#"children" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[changedObjects release];
}
- (void)addPostsObject:(Post *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:#"posts" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:#"posts"] addObject:value];
[self didChangeValueForKey:#"posts" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[changedObjects release];
}
So you can find that for Post, it is - (void)addPostsObject: (Post *) value
but for SubTab, it is - (void)addChildrenObject:(NSManagedObject *) value // value is NOT a SubTag
And I tried to check the element of posts and children to see if they can return the correct class information. And they did NOT.
Tag* data = ...
NSObject *a = [tmp.posts anyObject];
NSString *className = NSStringFromClass([a class]);
NSLog(#"I am a %#",className); //it says Post correctly.
Tag* data = ...
NSObject *a = [tmp.children anyObject];
NSString *className = NSStringFromClass([a class]);
NSLog(#"I am a %#",className); //it says **NSManagedObject** instead of **SubTag**
Even I changed - (void)addChildrenObject:(NSManagedObject *)value to - (void)addChildrenObject:(SubTag *)value, the result is the same.
I really can't figure out why. Can someone cast some light on it ?
Thanks a lot!
I deleted the original SubTag that xcode generated for me and let xcode generate again and the problem was solved.
I don't know why but did not bother to.
I am getting errors when trying to add items to a NSMutableArray which is encapsulated within an object.
Code follows:
#import <Foundation/Foundation.h>
#interface TestObject : NSObject {
NSMutableArray *myArray;
}
#property (nonatomic, retain) NSMutableArray *myArray;
#end
#import "TestObject.h"
#implementation TestObject
#synthesize myArray;
- (id) init {
if(self= [super init]){
// Initialise the Mutable Array
myArray = [[NSMutableArray alloc] init];
}
return self;
}
- (void) dealloc {
[super dealloc];
[myArray release];
}
#end
Calling:
TestObject *testObject = [[TestObject alloc] init];
NSString *someString = #"blah blah blah";
NSLog(#"%#", someString);
[testObject.myArray addObject:someString];
NSLog(#"Test Object Array Count: %#", [testObject.myArray count]);
[testObject release];
Can anyone tell me why this throws an error when calling count?
I have also tried the copy the Mutable Array to a local variable and get the same result when calling count on the local variable.
Warning warning warning!!!
[super dealloc] is the last thing you should do in your -dealloc method, not the first!
It's a good thing it just showed a warning, when I have done the same it has crashed.
The reason is that %# is an object placeholder. But the count method returns NSInteger which is a primitive datatype and the placeholder for it is %d, as you have correctly noted in the comment.
I hope to add objects to a NSMutableArray "myArray", The NSMutableArray is the array for FileObj which has a NSString property "fileName"
#import <UIKit/UIKit.h>
#interface FileObj : NSObject {
NSString *fileName;
}
-(void) setfileName:(NSString *)s ;
-(NSString *) getfileName ;
#end
//
// File.m//
#import "File.h"
#implementation FileObj
-(void) setfileName:(NSString *)s ;
{
fileName=s;
}
-(NSString *) getfileName ;
{
return fileName;
}
#end
I initialize the myArray here:
NSMutableArray *temarray;
temarray=[[NSMutableArray alloc] init];
self.myArray=temarray;
[temarray release];
the codes to add object to myArray
FileObj *newobj=[[FileObj alloc]init ];
NSString *fieldValue2 = [[NSString alloc] initWithUTF8String:#"aaaa"];
[newobj setfileName:fieldValue2];
[myArray addObject:newobj];
[fieldValue2 release]; //**if I enabled the line, it will cause crash**
//**if I disable the line, it will cause memory leak**
[newobj release];
Welcome any comment
Thanks
interdev
First you should look into ObjC naming conventions. There is no -get methods in ObjC. It's also a good idea to prefix your classes with your own 2 letters (like NS).
Your setter value assignment is invalid and the NSString initialization unnecessary.
I would strongly recommend introductory material to you!
#interface MYFileObject : NSObject {
NSString *_fileName;
}
- (void)setFileName:(NSString *)theString;
- (NSString *)fileName;
#end
and the implementation
#implementation MYFileObject
- (void)setFileName:(NSString *)theString {
[_fileName release];
_fileName = [theString copy];
}
- (NSString *)fileName {
return [[_fileName copy] autorelease];
}
- (void)dealloc {
[_fileName release];
[super dealloc];
}
#end
You would add an object like this...
NSMutableArray *myAry = [[NSMutableArray alloc] init];
MYFileObject *obj = [[MYFileObject alloc] init];
[obj setFileName:#"thefilename.txt"];
[myAry addObject:obj];
[obj release];
I would recommend using properties instead of defining your own getters/setters.
You could also use the NSMutableArrays' designated initializers for fast array creation.
Look here for how to use properties: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html
Why bother with getters and setters? Use declared property already!
#interface FileObj : NSObject {
NSString *fileName;
}
#property(retain,nonatomic) NSString* fileName; // <---
#end
...
#implementation FileObj
#synthesize fileName; /// <---
-(void)dealloc {
[fileName release]; // Remember to release the object on dealloc.
[super dealloc];
}
#end
...
FileObj *newobj=[[FileObj alloc] init];
NSString *fieldValue2 = [[NSString alloc] initWithUTF8String:#"aaaa"];
newobj.fileName = fieldValue2; /// <----
[myArray addObject:newobj];
[fieldValue2 release];
[newobj release];
The crash occurs because the NSString instance is not retained anymore.
A common pattern is to retain NSString properties, either declaratively with #property or by hand.
You should modify the setter like this:
-(void) setfileName:(NSString *)s ;
{
[s retain]; // <- Retain new value
[filename release]; // <- Release old value
fileName=s;
}