0

小さなプロジェクトがあり、コードに多くのリークがあることに気付きました。そこで、オートリリースを使い始めました。しかし、時々、リークを取り除くことができないか、autorelease を使用するとアナライザーが autorelease が多すぎると通知することがあります。これは、フォント、シャドウ、および現在の秒との位置合わせを含むクラス attributedTitle を返す関数です。私は自分が間違っていることを理解しようとしてしばらく遊んでいます。誰かがそれを見て、どこが間違っているのか教えてもらえますか?

- (NSAttributedString *)attributedTitle {
    NSMutableParagraphStyle *pStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
    [pStyle setAlignment: NSCenterTextAlignment];

    NSShadow *pShadow = [[[NSShadow alloc] init] autorelease];  

    [pShadow setShadowColor: [NSColor colorWithSRGBRed:0.11 green: 0.11 blue:0.11 alpha: 0.67]];
    [pShadow setShadowBlurRadius: 1.0];
    [pShadow setShadowOffset: NSMakeSize(0,1)];
    [pShadow set];

    NSMutableDictionary *attributes = [[[[NSMutableDictionary alloc] initWithObjectsAndKeys:
                                         [NSFont fontWithName: @"Arial Bold" size: 11], NSFontAttributeName,
                                         [NSColor colorWithDeviceWhite: 1.0 alpha: 0.83], NSForegroundColorAttributeName,
                                         pStyle, NSParagraphStyleAttributeName,
                                         pShadow, NSShadowAttributeName,
                                         nil] mutableCopy] autorelease];



    NSString *text = [[[NSString alloc] initWithFormat: @"%d", [[[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar]
                                                        components: NSSecondCalendarUnit fromDate: [[NSDate alloc] init]]second]] autorelease];

    NSAttributedString *result = [[[NSAttributedString alloc] initWithString: text attributes: attributes] autorelease];

    return result;

}

最初は、これはかなり短縮されていました - できれば変数を使用しませんでしたが、変数を追加したところ、それによってはるかに長くなりました - したがって、これは実際にはリークと自動リリースの単なる例です。

これももっと簡単にできると確信していますが、今はオートリリースの正しい使用とリークを取り除く方法について心配しています..そして、なぜリークがあるのか​​(コードもたくさんあります何が悪いのか理解できれば修正できます..)


わかりました、整理しました..漏れていません-短縮しました..

- (NSAttributedString *)attributedTitle {
    NSMutableParagraphStyle *pStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
    [pStyle setAlignment: NSCenterTextAlignment];

    NSShadow *pShadow = [[[NSShadow alloc] init] autorelease];  

    [pShadow setShadowColor: [NSColor colorWithSRGBRed:0.11 green: 0.11 blue:0.11 alpha: 0.67]];
    [pShadow setShadowBlurRadius: 1.0];
    [pShadow setShadowOffset: NSMakeSize(0,1)];
    [pShadow set];

    NSDictionary *attributes = [[[NSDictionary alloc] initWithObjectsAndKeys:
                                [NSFont fontWithName: @"Arial Bold" size: 11], NSFontAttributeName,
                                [NSColor colorWithDeviceWhite: 1.0 alpha: 0.83], NSForegroundColorAttributeName,
                                pStyle, NSParagraphStyleAttributeName,
                                pShadow, NSShadowAttributeName,
                                nil] autorelease];

    NSDateComponents *dc = [[[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease]
                            components: NSSecondCalendarUnit fromDate: [[[NSDate alloc] init] autorelease]];

    return [[[NSAttributedString alloc] initWithString: [[[NSString alloc] initWithFormat: @"%d", [dc second]] autorelease] attributes: attributes] autorelease];
}

しかし、これはどうですか?

SInt32 CFWeeksInYear(NSUInteger year)
{
    NSDateFormatter *dateFormat = [[[NSDateFormatter alloc] init] autorelease];
    [dateFormat setDateFormat:@"dd.MM.YYYY"];
    NSDate *tempMonth = [[[NSDate alloc] initWithString: [[[NSString alloc] initWithFormat: @"31.12.%ld", year] autorelease]] autorelease];
    SInt32 result = CFAbsoluteTimeGetWeekOfYear([tempMonth timeIntervalSinceReferenceDate], CFTimeZoneCopyDefault());
    return result;
}

SInt32 CFWeekOfYear(CFGregorianDate tempMonth)
{
    CFAbsoluteTime tempDate = CFGregorianDateGetAbsoluteTime (tempMonth, CFTimeZoneCopyDefault());
    return CFAbsoluteTimeGetWeekOfYear(tempDate, CFTimeZoneCopyDefault());
}

次の場所で漏れます。

SInt32 result = CFAbsoluteTimeGetWeekOfYear([tempMonth timeIntervalSinceReferenceDate], CFTimeZoneCopyDefault());

と:

CFAbsoluteTime tempDate = CFGregorianDateGetAbsoluteTime (tempMonth, CFTimeZoneCopyDefault());

さらには:

return CFAbsoluteTimeGetWeekOfYear(tempDate, CFTimeZoneCopyDefault());

CFTimeZoneCopyDefault() と関係があるようですが、ポインターを返すべきではありません..

4

2 に答える 2

2

あなたはCFTimeZoneCopyDefault「ポインターを返すべきではない..」と主張していますが、そうです。

CFTimeZoneCopyDefaultを返しますCFTimeZoneRef。それが何であるかを見てみましょう:

typedef const struct __CFTimeZone * CFTimeZoneRef;

はい、ポインターです。

このポインタは Cocoa オブジェクトへの参照ではありませんが、割り当てられたメモリへの参照です。Core Foundation の関数命名規則から、「コピー」という単語を含む CF 関数はメモリを割り当てていることがわかっています。つまり、メモリを使い終わったときにメモリを確実に解放するのはあなた次第です。

そのメモリ*を解放する 1 つの方法は、Core Foundation 関数を使用することCFRelease()です。それを念頭に置いて、コードを少し見直してみましょう。

SInt32 CFWeekOfYear(CFGregorianDate tempMonth)
{
    CFAbsoluteTime tempDate = CFGregorianDateGetAbsoluteTime (tempMonth, CFTimeZoneCopyDefault());
    return CFAbsoluteTimeGetWeekOfYear(tempDate, CFTimeZoneCopyDefault());
}

への参照を保持し、CFTimeZoneRef完了したら破棄できます。

SInt32 CFWeekOfYear(CFGregorianDate tempMonth)
{
    CFTimeZoneRef tzRef = CFTimeZoneCopyDefault();
    CFAbsoluteTime tempDate = CFGregorianDateGetAbsoluteTime (tempMonth, tzRef);
    SInt32 result = CFAbsoluteTimeGetWeekOfYear(tempDate, tzRef);
    CFRelease(tzRef);
    return result;
}

もちろん、実際のアプリケーションは NULL 応答 (など) をチェックしますが、その考えはわかります。

autorelease について: メモリ管理の問題に対する万能薬ではありません。あなたの例では大丈夫ですが、自動解放プールが非常に大きくなったために、設計が不適切なアプリケーションが物理 RAM を使い果たすのを見てきました。ループや再帰メソッドなどの場所で自動解放されたオブジェクトに依存するように注意してください。この種の問題を回避するために、独自の自動解放プールを慎重に割り当てる (および解放する) ことができます。このフォーラムでは、私は非常に詳細にしか説明できないので、以下を読むことをお勧めします。

Apple メモリ管理ガイド

あなたの努力に幸運を。

*CFTimeZoneは、対応する Cocoa と「無料でブリッジ」されています。これは、メッセージをそれに送信 (キャスト)NSTimeZoneすることもできることを意味します。releaseNSTimeZone *

于 2012-04-05T20:24:07.143 に答える
0

これがCFのリリース方法です..

CFTimeZoneRef tz = CFTimeZoneCopyDefault();

/* Do what you need to do with it */

CFRelease(tz);
于 2012-04-05T20:44:23.803 に答える