-1

I have the following problem:

in header;

GDataXMLDocument *doc;
NSString *xmlBody;
@property (nonatomic,copy) NSString *xmlBody;
@property (nonatomic,retain) GDataXMLDocument *doc;

in m

#import "tchLoader.h"
#import "Variable.h"
#import "DisplayVariable.h"
@implementation tchLoader
@synthesize responseXMLData,lastLoadedResponseXMLData;
@synthesize conn;
@synthesize doc;
@synthesize xmlBody;


- (void)loadXML:(id<tchLoaderDelegate>)delegate {
    NSString *theBaseXML= @"some xml code here"
    if (self.xmlBody==nil){     
        self.xmlBody=theBaseXML;
    }
    _delegate = delegate;
    /*
    SCNetworkReachabilityFlags flags;
    SCNetworkReachabilityRef reachability =  SCNetworkReachabilityCreateWithName(NULL, [@"www.alues.com" UTF8String]);
    SCNetworkReachabilityGetFlags(reachability, &flags);

        // The reachability flags are a bitwise set of flags that contain the information about
        // connection availability
    BOOL reachable = ! (flags & kSCNetworkReachabilityFlagsConnectionRequired);
    */
    NSString *soapMessage =self.xmlBody;    
    NSURL *url = [NSURL URLWithString:@"https://area.tch-values.com/soapmwp/mws"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMessage length]];
    [request addValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request addValue: @"http://www.tch-values.com/webservice" forHTTPHeaderField:@"SOAPAction"];
    [request addValue: msgLength forHTTPHeaderField:@"Content-Length"];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];

    if ([NSURLConnection canHandleRequest:request] && true) {
        self.conn = [[NSURLConnection alloc ]initWithRequest:request delegate:self];
        if (self.conn) {
            self.responseXMLData = [NSMutableData data];
        }
    }
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"ERROR with theConenction");
    [self.doc release];
    [self.conn release];
    [self.responseXMLData release];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    NSLog(@"DONE. Received Bytes: %d", [self.responseXMLData length]);  

        //[self.conn release];
    if ([_delegate respondsToSelector:@selector(xmlDidFinishLoading)]) {
        [_delegate xmlDidFinishLoading];
    }
}

-(void)insertAnswers: (NSMutableArray*) answeredVariables{



    for (Variable * variable in answeredVariables)
    {
        NSInteger pageID=[variable pageId];
        //NSMutableArray *answers=[NSMutableArray arrayWithCapacity:[[variable variableValues] count]];
        NSString *path = [NSString stringWithFormat:@"//inferenceresponse/state/variable[pageId=%d]/valuedefinition",pageID];
        NSArray *valueElement = [doc nodesForXPath:path error:nil];
        GDataXMLElement *valueDefinitionElement;

        if (valueElement.count > 0) {           
            valueDefinitionElement= (GDataXMLElement *) [valueElement objectAtIndex:0];
        }

        GDataXMLElement * sourceElement = [GDataXMLNode elementWithName:@"source"];
        [sourceElement addAttribute:[GDataXMLNode attributeWithName:@"type" stringValue:@"ask user"]];  
        GDataXMLElement * timeStampElement = [GDataXMLNode elementWithName:@"timestamp" stringValue:@"12345"];
        [sourceElement addChild:timeStampElement];      
        GDataXMLElement * assignmentElement = [GDataXMLNode elementWithName:@"assignmentnumber" stringValue:@"6"];

        for(NSString *answer in variable.variableValues){
            GDataXMLElement * variableValueElement = [GDataXMLNode elementWithName:@"variablevalue"];
            [variableValueElement addAttribute:[GDataXMLNode attributeWithName:@"value" stringValue:answer]];
            [valueDefinitionElement addChild:variableValueElement];
        }

        [valueDefinitionElement addChild:sourceElement];
        [valueDefinitionElement addChild:assignmentElement];    
    }

        NSData *xmlData = self.doc.XMLData;
        NSString *theXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] encoding:NSUTF8StringEncoding];  
        theXML =[theXML stringByReplacingOccurrencesOfString:@"inferenceresponse" withString:@"inferencerequest"];
        theXML =[theXML stringByReplacingOccurrencesOfString:@"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" withString:@"<SOAP-ENV:Envelope  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"> "];
        theXML =[theXML stringByReplacingOccurrencesOfString:@"xmlns=\"\"" withString:@"xmlns=\"http://www.tch-values.com/xml/webservice\""];       
        theXML =[theXML stringByReplacingOccurrencesOfString:@"<state goalreached=\"false\">" withString:@"<state goalreached=\"false\"> <value>PlanKB</value> <goalvariable>myGoal</goalvariable> "];  
        self.xmlBody=theXML;
        [theXML release];
        //[self.doc release];
        NSLog(self.xmlBody);        
}

- (NSMutableArray*)variablesForPageID:(NSString*)pageID {
    NSMutableArray *variables = nil; 
    if (self.responseXMLData) {
        variables = [NSMutableArray arrayWithCapacity:10];
        NSData *xmlData = self.responseXMLData;
        NSError *error;
        self.doc=nil;
        doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
        if (self.doc == nil) { 
            return nil;
        }

        NSArray *status = [doc nodesForXPath:@"//inferenceresponse/state[@goalreached='true']" error:nil];
        if([status  count]==1){
            self.xmlBody=nil;
            Variable *variable=[[Variable alloc] init];

            NSString *path = [NSString stringWithFormat:@"//inferenceresponse/state/displayvariables/display[@isDisplayShown='false']"];
            NSArray *displayVariablesElements = [doc nodesForXPath:path error:nil];
            NSMutableArray *disps=[[NSMutableArray alloc] init];

            if(displayVariablesElements.count >0){          
                for(GDataXMLElement *disElement in displayVariablesElements){

                    DisplayVariable *disVar=[[DisplayVariable alloc] init];
                    NSArray *disPageid = [disElement nodesForXPath:@"@displayPageId" error:nil];
                    GDataXMLElement *Pageid = (GDataXMLElement *) [disPageid objectAtIndex:0];
                    disVar.displayPageId =Pageid.stringValue;

                    NSArray *disName = [disElement nodesForXPath:@"displayname" error:nil];
                    if(disName.count >0){
                        GDataXMLElement *disNam = (GDataXMLElement *) [disName objectAtIndex:0];
                        disVar.displayName =disNam.stringValue;
                    }

                    NSArray *disValue = [disElement nodesForXPath:@"displayvalue" error:nil];
                    if(disValue.count >0){
                        GDataXMLElement *disVal = (GDataXMLElement *) [disValue objectAtIndex:0];
                        disVar.displayValue =disVal.stringValue;
                    }

                    NSArray *disId = [disElement nodesForXPath:@"@id" error:nil]; 
                    GDataXMLElement *disIdEl = (GDataXMLElement *) [disId objectAtIndex:0];
                    disVar.pageId =[disIdEl.stringValue  intValue];

                    [disps addObject:disVar];
                    [disVar release];
                }
                variable.displayVariables=disps;
                [disps release];
            }   
            variable.lastVariableofConsultation=YES;
            [variables addObject:variable];
            [variable release];
        }       
            else{
                NSArray *inferenceMembers = [doc nodesForXPath:@"//inferenceresponse/state/variable[not(valuedefinition/variablevalue)]" error:nil];
                  for (GDataXMLElement *variableElement in inferenceMembers) {
                        Variable *variable=[[Variable alloc] init];
                        NSArray *items = [variableElement nodesForXPath:@"domaindefinition/domain/enumType/domainitem" error:nil];
                        NSMutableArray *domainItems = [NSMutableArray arrayWithCapacity:items.count];

                        for (int i=0; i<items.count;i++) {
                            GDataXMLElement *domainItem = (GDataXMLElement *) [items objectAtIndex:i];
                            [domainItems addObject:domainItem.stringValue];
                        }   
                        variable.domainItems=domainItems;               
                        NSArray *names = [variableElement nodesForXPath:@"name/@name" error:nil];

                        if (names.count > 0) {
                            GDataXMLElement *nameElement = (GDataXMLElement *) [names objectAtIndex:0];
                            variable.variableName = nameElement.stringValue;
                        }
                        NSArray *pageId = [variableElement nodesForXPath:@"pageId" error:nil];


        }
    }
    return variables;   
}


- (void)dealloc {

    [responseXMLData release] ;
    [lastLoadedResponseXMLData release] ;
    [conn release];
    [doc release];
    [xmlBody release];
    [super dealloc];
}


@end


#import "tchLoader.h"
#import "Variable.h"
#import "DisplayVariable.h"
@implementation tchLoader
@synthesize responseXMLData,lastLoadedResponseXMLData;
@synthesize conn;
@synthesize doc;
@synthesize xmlBody;

If I [theXML release] it crashes, If I dont release theXML then it works perfect but I see memory leak in simulator Instruments tool. (There are also lots of memory leaks I see in this code but couldnt figure out by instrumnets tool what is going on)

Spring
  • 11,333
  • 29
  • 116
  • 185
  • what is NSString *newXML = [[NSString alloc] initwith **someobjects**]; and what kind of value it contains – Praveen-K Aug 03 '11 at 14:26
  • Maybe you have an extra release somewhere else, and the extra retain balances it. – LaC Aug 03 '11 at 14:27
  • 1
    Post the crash. The code you've shown is conceptually correct; as Control-V says, details on that initialization would be helpful. – bbum Aug 03 '11 at 14:27
  • @Control-V tnx I updated – Spring Aug 03 '11 at 14:34
  • You are allocating theXML and releasing newXML, is that correct? – Praveen S Aug 03 '11 at 14:35
  • Your code looks correct, unfortunately for you. – iandotkelly Aug 03 '11 at 14:43
  • 2
    you're allocating it, the accessor is copying it, then you are releasing it. the original is not being retained, `newXML` is a bad reference after the release – bshirley Aug 03 '11 at 19:29
  • @bshirley tnx how should i do? shouldnt I in the end release whatever I allocate? – Spring Aug 03 '11 at 20:09
  • @bshirley when I copy dont I have the owbership of the object, means retain count will stay +1 and will not freed from memory? – Spring Aug 03 '11 at 20:48
  • What happens if you try NSString *newXml = [[[NSString alloc]init....]autorelease]; and then remove your release - does it still crash when the autorelease pool is released? – Richard Baxter Aug 03 '11 at 22:38
  • @XDev, are you accessing `newXML` after you release it? if not, then that's not your problem. - - - since you've only provided code snippits, we're left to guess – bshirley Aug 03 '11 at 22:48
  • @bshirley I updated my code pls check – Spring Aug 03 '11 at 23:01
  • did you change `newXML` to `theXML`? your text still references the previous. where is it crashing? what is the crash saying? – bshirley Aug 03 '11 at 23:54
  • @bshirley zombie says I sent massage to deallocated object – Spring Aug 04 '11 at 00:16
  • 3
    You should avoid writing NSLog(self.xmlBody), and should write NSLog(@"%@",self.xmlBody). If the string for xmlBody contained "%@" anywhere inside of it, the log would crash. – Jon Hess Aug 04 '11 at 00:42
  • @Jon Hess tnx could you also helpme with te maion problem – Spring Aug 04 '11 at 01:08

4 Answers4

1

This looks wrong:

[doc release];

Why are you releasing an object managed by a property?

In your @synthesize statements change them to:

@synthesize doc = doc_;
@synthesize xmlBody = xmlBody_;

Then fix all the resulting errors to go through the property, releasing the properties ONLY in dealloc.

Edit:

You say it crashes releasing theXML. This code is wrong:

NSString *theXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] encoding:NSUTF8StringEncoding];  
        theXML =[theXML stringByReplacingOccurrencesOfString:@"inferenceresponse" withString:@"inferencerequest"];
[theXML release];

You alloc a string, replace that variable with the "stringByReplacing..." call with a string that is autoreleased, then try to release the resulting string that is autoreleased which will crash. When you don't need to keep a string around after the method you are in, ALWAYS use autorelease. The correct code is:

 NSString *theXML = [[[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] encoding:NSUTF8StringEncoding] autorelease];  
            theXML =[theXML stringByReplacingOccurrencesOfString:@"inferenceresponse" withString:@"inferencerequest"];

And take out [theXML release] - there will be no leak.

I think you should really switch to using ARC as soon as you possibly can... it will save you from a lot of such misunderstandings.

Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150
  • tnx could you pls explain what does this mean? synthesize doc = doc_ I changed my class to be normal and not singleton but still same error..and I want to relaese it cause that class handles the internet connection and dont want to deallocate and create the class again for each connection..should I only nillfy the objects? – Spring Aug 03 '11 at 22:24
  • This is a very common convention. The synthesize instance variable with be given the name on the rhs (right hand side) of the statement. It help you and other readers of the code remind themselves that they are directly accessing an ivar an not using the property getter/setter to access it. --- my preference is `doc = _doc` (and Xcode 4.2 will code complete that convention) – bshirley Aug 04 '11 at 03:11
  • In theory Apple states that leading "_" are reserved for apple use only and you should not use them... in practice Apple will not base rejections on that, and as you say XCode even completes things that way... but I still like to put them at the end. I also feel they are less ugly that way. – Kendall Helmstetter Gelner Aug 04 '11 at 04:05
1

If you want to release an ivar/property(retain), this is not how to to it:

[self.doc release];

instead:

self.doc = nil;
bshirley
  • 8,217
  • 1
  • 37
  • 43
  • sorry confused which one is correct above? also someone said I should not release objects if I get them by property? – Spring Aug 04 '11 at 00:20
0

One "problem" with singleton objects is that they appear to leak. If you create an object and never destroy it, Instruments says it's a leak, even if your intention was never to release it.

Richard
  • 3,316
  • 30
  • 41
  • problem is not leakage, but it crashes if I release it thats the problem. If I dont release it works then I am against memory rules by not releasing what I am allocating – Spring Aug 03 '11 at 14:51
  • @XDeveloper If you release it then it isn't a singleton. – Richard Aug 03 '11 at 14:58
  • But I'm not releasing xmlBody which I declared in header and syntesized, I release an object I just created in a method. So Singleton means I can not release "any" object in any way in its methods? – Spring Aug 03 '11 at 15:18
  • Clearly you should release those kinds of "disposable" objects. – Richard Aug 03 '11 at 15:29
  • and why does it crash when I relaese? – Spring Aug 03 '11 at 15:36
  • 1
    Singletons do not show up as leaks, the Leaks tool does not show static variables as leaks. If it does show up in leaks you've not written a singleton, but a class that you are managing badly. – Kendall Helmstetter Gelner Aug 03 '11 at 19:51
  • When I said Instruments I was thinking of the static analysis (build & analyze). Caveat: I haven't tried it in Xcode 4+. – Richard Aug 03 '11 at 20:04
  • @Kendall Helmstetter Gelner could you tell how can I fix this? should I also allocate the xmlBody? – Spring Aug 03 '11 at 20:13
  • @richard- Singletons have never shown up in any version of the analyzer, in any version of XCode. If they are they are not singletons. By definition a singleton is not a leak. If it shows up and you think it's a singleton, something is wrong with how the singleton is written. A Singleton at the core of things is simply a static variable holding a single instance used across the lifetime of the application. – Kendall Helmstetter Gelner Aug 03 '11 at 21:54
  • @Xdev: Sorry, but I don't see any code for how the singleton is implemented, I have no idea how to advise. Google for common objective-C singletons and make sure your singleton works like them. – Kendall Helmstetter Gelner Aug 03 '11 at 21:55
  • @Kendall Helmstetter Gelner I updated my code pls check not a singleton anymore nut same problem – Spring Aug 03 '11 at 23:03
  • @Kendall right, the "static variable holding a single instance" is never released. If you have a Singleton that Xcode's static analyzer doesn't report as a leak, please share it so that I can write better singletons. – Richard Aug 04 '11 at 15:00
  • @Kendall Helmstetter Gelner thx for your great help could you also have a look at http://stackoverflow.com/questions/6942439/objectivec-ivars-or-property – Spring Aug 04 '11 at 15:06
  • @richard All you need to do is mark the instance variable holding the singleton instance as static, I've never had the analyzer mention it - there are lots of singleton examples around, all of them have never triggered the analyzer - even just something at simple as "static MyClass *instance; -(MyClass *) sharedInstance { if ( instance == nil ) {instance = [[MyClass alloc] init];} } works just fine for me, no analyzer warnings. – Kendall Helmstetter Gelner Aug 04 '11 at 18:28
0
NSData *xmlData = doc.XMLData;
newXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] 
encoding:NSUTF8StringEncoding];

What is your newXML? is it a ivar and synthesize it and retain it? if yes the compiler will automatically generate getter and setter methods.

NSData *xmlData = doc.XMLData;
self.newXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] 
encoding:NSUTF8StringEncoding];
self.timestamp = nil;

If its not property then

NSString* newXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] 
encoding:NSUTF8StringEncoding];   
self.xmlBody=newXML;   
[newXML release]; 
Praveen-K
  • 3,401
  • 1
  • 23
  • 31
  • Then its an ivar, then try with my second code which i have given already above under the "If its not property then" the Instrument should not complain about leak. – Praveen-K Aug 03 '11 at 16:36
  • did you remove the encoding on purpose? if not thats the same code as mine and it crashes? – Spring Aug 03 '11 at 16:40