Cocoa String Noob - NSMutableString appendString PROBLEM

Discussion in 'Mac Programming' started by tjw09003, Feb 11, 2010.

  1. tjw09003 macrumors newbie

    Joined:
    Feb 11, 2010
    #1
    I recently switched to mac and I am trying to write my first mac program.

    I have a problem with NSMutableString's

    The code is much more complex but I've narrowed it down to this type of problem.


    Code:
    
    NSMutableString* testString;
    
    - (IBAction)sendTestValue:(id)sender{
         [txt_value setStringValue:testString];
    }
    
    - (IBAction)setTestValue:(id)sender{
    
         testString = @"test ";
         //[testString appendString:@"append worked!!];
    
    }
    
    If I uncomment the line [testString appendString:mad:"append worked!!];
    and run setTestValue when I try to run sendTestValue the program crashes with "EXC_BAD_ACCESS"

    Any ideas why?
     
  2. HexMonkey Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #2
    The problem is the line

    Code:
    testString = @"test ";
    Here, @"test" is a string literal which implicitly creates an NSString object (which is immutable). Just because you store it in a variable of type NSMutableString does not make it mutable. When you try and modify it later, you then run into problems since you can't modify an immutable string.

    To fix this, try replacing that line with the following:
    Code:
    [testString release];
    testString = [[NSMutableString alloc] initWithString:@"test "];
     
  3. tjw09003 thread starter macrumors newbie

    Joined:
    Feb 11, 2010
    #3
    ok, so I tried this

    Code:
    NSMutableString* testString;
    
    - (IBAction)sendTestValue:(id)sender{
         [txt_value setStringValue:testString];
    }
    
    - (IBAction)setTestValue:(id)sender{
    
         [testString release];
         testString = [[NSMutableString alloc] initWithString:@"test "];
         [testString appendString:@"append worked!!];
    
    }
    
    It still crashes with EXC_BAD_ACCESS :(

    It crashes ONLY if I first run setTestValue
    and then I run sendTestValue

    ONLY THEN will it crash, when sendTestValue runs after setTestValue.

    txt_value is a NSTextField by the way.
     
  4. HexMonkey Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #4
    That error sounds like you have a memory problem somewhere. Could testString or txt_value somehow be released between the calls to setTestValue and sendTestValue? You might need to post more of your code for us to be able to help - is there more in the setTestValue method than what you've posted?
     
  5. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #5
    If that's your exact code, then you're missing a closing quote in this line:
    Code:
         [testString appendString:@"append worked!!];
    
    after the !! and before the ]. I'm surprised it would compile.

    If that's not your exact code, then please post your exact code. Copy and paste it, don't retype it.
     
  6. tjw09003 thread starter macrumors newbie

    Joined:
    Feb 11, 2010
    #6
    Here's my exact code.

    My first program on a mac so go easy on me, it's very unprofessional :p

    Code:
    #import "appControl.h"
    
    NSString* sourcePath = @"";
    NSString* elfPath = @"";
    NSString* hexPath = @"";
    NSString* finalCMD = @"";
    NSString* execCMD = @"";
    NSMutableArray* Arguments; 
    
    
    @implementation appControl
    
    - (IBAction)setCommand:(id)sender{			//--------"SET COMMAND" BUTTON------------------------------
    	
    	Arguments = [NSMutableArray arrayWithObjects:nil];      //---RESET ARGUMENTS
    	
    	execCMD = @"avr-gcc";									//---SET avr-gcc TO EXECUTE
    	
    	finalCMD = @"avr-gcc ";									//---RESET COMMAND STRING
    	
    	[Arguments addObject:									//---SET CLK FREQUENCY
    		[@"-DF_CPU=" stringByAppendingString:
    			[txt_freq stringValue]]];
    	
    	if ([deviceSelection indexOfSelectedItem] == 0) {		//---CHECK AND SET DEVICE TYPE
    		[Arguments addObject:@"-mmcu=atmega8"];				
    	}
    	
    	if ([deviceSelection indexOfSelectedItem] == 1) {		
    		[Arguments addObject:@"-mmcu=atmega168"];
    	}
    	
    	if ([deviceSelection indexOfSelectedItem] == 2) {		
    		[Arguments addObject:@"-mmcu=atmega328"];
    	}
    	
    	
    	[Arguments addObject:@"-o"];							//---ADD -o FLAG
    	
    	[Arguments addObject:elfPath];   //<---**THIS IS WHERE IT CRASHES
    	
    	[Arguments addObject:sourcePath];
    	
    	
    	
    	
    	//-------READ ARGUMENTS INTO finalCMD STRING
    	int i;
    	for(i=0;i<[Arguments count];i++){
    		finalCMD = [finalCMD stringByAppendingString:[@" " stringByAppendingString:[Arguments objectAtIndex:i]]];
    	}
    	
    	//-------SEND finalCMD STRING TO TEXT OUTPUT
    	[txt_finalCMD setStringValue:finalCMD];
    	
    }
    
    - (IBAction)getFile:(id)sender{
    	
    	
    	NSString* prjName = [txt_fileloc stringValue];  //Get project name
    	NSString* prjDir = @"/avr/prj/";  //Projects directory
    	
    	
    	sourcePath = [prjDir stringByAppendingString:[prjName stringByAppendingString:[@"/" stringByAppendingString:[prjName stringByAppendingString:@".c"]]]];
    	elfPath = [prjDir stringByAppendingString:[prjName stringByAppendingString:[@"/" stringByAppendingString:[prjName stringByAppendingString:@".out"]]]];
    	hexPath = [prjDir stringByAppendingString:[prjName stringByAppendingString:[@"/" stringByAppendingString:[prjName stringByAppendingString:@".hex"]]]];
    
    	
    	[lbl_sourceFile setStringValue:[@"Source File: " stringByAppendingString:sourcePath]];
    	[lbl_elfFile setStringValue:[@"ELF File: " stringByAppendingString:elfPath]];
    	[lbl_hexFile setStringValue:[@"HEX File: " stringByAppendingString:hexPath]];
    	
    
    	
    	
    	
    }
    
    
    @end
    
    It crashes when running setCommand after getFile
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
  8. tjw09003 thread starter macrumors newbie

    Joined:
    Feb 11, 2010
    #8
    it's the elfPath string, I changed it back to a NSString when I was playing around with it trying to get it to work.



    EDIT: It was also the sourcePath string which I changed to NSString too.
     
  9. HexMonkey Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #9
    The problem is that sourcePath, elfPath and hexPath are created with convenience methods in getFile. This means that they are autoreleased, so by the time setCommand is run the memory for them will be deallocated. Then when you use them, the program crashes accessing this memory. You need to retain them before the end of the getFile method and release them at some later point to avoid a memory leak (I'm assuming here that you aren't using garbage collection).

    If this doesn't make a lot of sense, I'd recommend reading the Memory Management Programming Guide for Cocoa.
     
  10. tjw09003 thread starter macrumors newbie

    Joined:
    Feb 11, 2010
    #10
    How would I retain them and prevent them from autoreleasing after getFile?


    EDIT:
    I'll rewrite this code from scratch.


    What would be a better way of creating a global NSString?
     
  11. HexMonkey Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #11
    It's probably easiest if you read up on memory management in general, and then it should all make sense. Some more resources:

    If you are developing only for Mac OS X 10.5 or later then you can use garbage collection and not have to worry about memory management. See Introduction to Garbage Collection if this is the case. If you ever want to develop for older versions of Mac OS X or for the iPhone, you'll need to know how to do memory management yourself though, so should read up on some of the links above.
     
  12. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #12
    That question is answered in the Memory Management Guide. It will be simpler if you read the guide first, then ask questions after.
     
  13. tjw09003 thread starter macrumors newbie

    Joined:
    Feb 11, 2010
    #13
    I guess I'll start reading up on memory management.


    EDIT: Thanks everyone, I got it to work.

    I added [sourcePath retain];
    and it works :)
     

Share This Page