gpt4 book ai didi

xcode - 为什么我的代码会泄漏以及如何正确使用自动释放..? [ cocoa /xcode]

转载 作者:行者123 更新时间:2023-12-03 17:42:14 25 4
gpt4 key购买 nike

我有一个小项目,我注意到我的代码中有很多泄漏。所以我开始使用autorelease。但有时,我只是无法消除泄漏,或者使用自动释放会导致分析器告诉我有太多自动释放。这是一个返回类 attributeTitle 的函数,其中包含字体、阴影和与当前秒的对齐方式。我已经玩了一段时间试图意识到我做错了什么。有人可以看一下并告诉我哪里出了问题吗?

- (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() 有关,但它不应该返回指针..

最佳答案

您认为 CFTimeZoneCopyDefault “不应该返回指针..”,但事实确实如此。

CFTimeZoneCopyDefault 返回一个 CFTimeZoneRef。让我们看看那是什么:

typedef const struct __CFTimeZone * CFTimeZoneRef;

是的,它是一个指针。

该指针不是对 Cocoa 对象的引用,但它仍然是对已分配内存的引用。从Core Foundation中的函数命名约定中我们知道,任何带有“copy”一词的CF函数都在分配内存。这意味着您需要确保在使用完内存后释放内存。

释放内存*的一种方法是使用 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:它不是解决内存管理问题的 Elixir 。在您的示例中,您做得很好,但我看到设计糟糕的应用程序耗尽了物理 RAM,因为自动释放池变得如此之大。在循环和递归方法等地方要小心依赖自动释放的对象;您可以明智地分配自己的自动释放池(并释放它们)以避免此类问题。在这个论坛上,我只能写这么冗长,所以我建议阅读:

Apple Memory Management Guide

祝您一切顺利。

*CFTimeZone 与 Cocoa 对应的 NSTimeZone 是“免费桥接”,这意味着您可以向其发送 release 消息(也转换为 NSTimeZone *)。

关于xcode - 为什么我的代码会泄漏以及如何正确使用自动释放..? [ cocoa /xcode],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10025897/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com