用于iPhone的SudzC似乎每个Web服务调用都会泄漏1kB

时间:2012-03-16 16:02:28

标签: iphone objective-c ios soap sudzc

Instruments报告了每次调用Soap Web服务时泄漏的2个对象,其中包含由SudzC生成的代码。

我已经缩小了一个简单的案例,使用代码调用免费的公共Web服务(http://www.webservicex.net/geoipservice.asmx?WSDL)并且没有身份验证。 不幸的是,运行SudzC项目需要大量设置,但是您可以通过将WSDL URL放入http://www.sudzc.com/并选择“来自iOS的Objective-C”来查看生成的代码。

Leaked Object   #   Address Size    Responsible Library Responsible Frame
Malloc 1.00 KB,     0x5035400   1.00 KB Foundation-[NSCFString appendString:]
NSCFString,     0x4c3d390   32 Bytes    Foundation  -[NSPlaceholderMutableString init]

每个对象的调用堆栈是

3 Foundation -[NSCFString appendString:]
4 SoapDemo +[Soap createEnvelope:forNamespace:forParameters:withHeaders:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/Soap/Soap.m:50
5 SoapDemo +[Soap createEnvelope:forNamespace:withParameters:withHeaders:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/Soap/Soap.m:114
6 SoapDemo -[WSXGeoIPService GetGeoIP:action:IPAddress:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/Generated/WSXGeoIPService.m:55
7 SoapDemo -[SoapDemoViewController callWebService] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/SoapDemoViewController.m:14
8 SoapDemo -[SoapDemoViewController press:] /Users/user1/Desktop/SRC/SoapDemo/SoapDemo/SoapDemoViewController.m:19

主叫代码:

- (IBAction)press:(id)sender {
    NSLog(@"pressed");
    [self callWebService];
}

-(void)callWebService {
    WSXGeoIPService* service = [WSXGeoIPService service];
    [service GetGeoIP:self action:@selector(handleResponse:) IPAddress:@"209.85.147.103"];
}

-(void) handleResponse:(id)value{
    NSLog(@"%@", value);
}

根据[Soap createEnvelope]中的工具,Soap.m中的违规行看起来非常无害(标有评论)。

+ (NSString*) createEnvelope: (NSString*) method forNamespace: (NSString*) ns forParameters: (NSString*) params withHeaders: (NSDictionary*) headers
{
    NSMutableString* s = [NSMutableString string];
    [s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
    [s appendFormat: @"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns=\"%@\">", ns];
    if(headers != nil && headers.count > 0) {
        [s appendString: @"<soap:Header>"];
        for(id key in [headers allKeys]) {
            if([[headers objectForKey: key] isMemberOfClass: [SoapNil class]]) {
                [s appendFormat: @"<%@ xsi:nil=\"true\"/>", key];
            } else {
                [s appendString:[Soap serializeHeader:headers forKey:key]];
            }
        }
        [s appendString: @"</soap:Header>"];
    }
    [s appendString: @"<soap:Body>"];
    [s appendFormat: @"<%@>%@</%@>", method,[params stringByReplacingOccurrencesOfString:@"&" withString:@"&amp;"], method];
    [s appendString: @"</soap:Body>"];
    [s appendString: @"</soap:Envelope>"]; // *** this is reported as causing the leak ***
    return s;
}

我已尝试修改方法(通过组合appendString调用,添加一些虚拟日志记录等)但泄漏始终发生在此方法中。

我可以想到几个可能性:

  • 代码中的其他地方有泄漏,而仪器识别错误。
  • appendString使用不正确。
  • Apple的NSMutableString appendString方法存在泄漏。
  • 没有实际泄漏。

任何人都可以推断出发生了什么(或者如何找到它)?

我正在使用iOS SDK 4.3。

计划B是将项目转换为自动参考计数...

1 个答案:

答案 0 :(得分:1)

对于那些不这样做的人,请按照我的更改来修复您的泄漏,因为它完美无缺:

  1. 在SoapRequest.h中将变量声明id postData替换为NSString* postData
  2. 在SoapRequest.h中将其属性声明替换为@property (copy, nonatomic) NSString* postData(此处,我还将所有NSString属性的转换更改为“copy”)
  3. 在SoapRequest.m中,方法(SoapRequest*) create: (SoapHandler*) handler action: (SEL) action urlString: (NSString*) urlString soapAction: (NSString*) soapAction postData: (NSString*) postData deserializeTo: (id) deserializeTo 将行request.postData = [postData retain]更改为request.postData = postData
  4. 这3个步骤将解决您的问题。希望它也将在SudzcC框架中实现。