1

Instruments は、SudzC によって生成されたコードを使用して Soap Web サービスを呼び出すたびに 2 つのオブジェクトがリークしたことを報告しています。

無料のパブリック 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 呼び出しを組み合わせたり、ダミーのログを追加するなどして)、このメソッドで常にリークが発生します。

いくつかの可能性を考えることができます:

  • コードの別の場所にリークがあり、Instruments が誤って特定しています。
  • appendString が正しく使用されていません。
  • Apple の NSMutableString appendString メソッドにリークがあります。
  • 実際の漏れはありません。

何が起こっているのか(またはこれを見つける方法)を誰でも推測できますか?

iOS SDK 4.3 を使用しています。

プラン B は、プロジェクトを自動参照カウントに変換することです...

4

1 に答える 1

1

そうでない場合は、私の変更に従ってリークを修正してください。完全に機能するためです。

  1. SoapRequest.h で、変数宣言id postDataを次のように置き換えます。NSString* postData
  2. SoapRequest.h で、そのプロパティ宣言を次のように置き換えます@property (copy, nonatomic) NSString* postData(ここでは、さらにすべての NSString プロパティ宣言を「コピー」に変更しました)。
  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ます。

この3つのステップで問題が解決します。SudzcC フレームワークにも実装されることを願っています。

于 2012-10-04T09:54:15.660 に答える