gpt4 book ai didi

cocoa - 字典的深层复制在 Xcode 4.2 中给出分析错误

转载 作者:行者123 更新时间:2023-12-03 16:16:00 24 4
gpt4 key购买 nike

我在 NSDictionary 类别中有以下方法来进行深度复制,效果很好。

我刚刚从 Xcode 4.1 升级到 4.2,Analyze 函数针对此代码给出了两个分析器警告,如下所示:

- (id)deepCopy;
{
id dict = [[NSMutableDictionary alloc] init];
id copy;

for (id key in self)
{
id object = [self objectForKey:key];

if ([object respondsToSelector:@selector(deepCopy)])
copy = [object deepCopy];
else
copy = [object copy];

[dict setObject:copy forKey:key];

// Both -deepCopy and -copy retain the object, and so does -setObject:forKey:, so need to -release:
[copy release]; // Xcode 4.2's Analyze says this is an incorrect decrement of the reference count?!
}

return dict; // Xcode 4.2's Analyze says this is a potential leak
}

这些错误是否存在于 Xcode 分析器中,或者我可以进行哪些更改来避免这些警告?

我还没有使用 ARC,但我很感兴趣是否需要进行其他更改来支持此方法的 ARC。

最佳答案

据推测,这是因为 deepCopy 不以 copy 前缀开始

因此,您可能想要更改为诸如 copyWithDeepCopiedValues (或类似的内容)之类的内容,然后查看分析器是否对此进行标记。

更新

正如 Alexsander 所指出的,您可以使用属性来表示引用计数意图。这应该(IMO)是规则的异常(exception),并且很少使用(如果有的话)。就我个人而言,我不会对 objc 方法使用属性,因为它很脆弱。

到目前为止,我使用的唯一属性是 consume,每次我使用这些属性时都是在静态类型上下文中(例如 C 函数和 C++ 函数和方法)。

应尽可能避免使用属性的原因:

1) 为了程序员的利益,坚持约定。代码比较清晰,不需要引用文档。

2) 该方法很脆弱。您仍然可以引入引用计数不平衡,并且属性可以用于由于属性冲突而引入构建错误。

以下案例均启用了 ARC 构建:

案例#1

#import <Foundation/Foundation.h>

@interface MONType : NSObject

- (NSString *)string __attribute__((objc_method_family(copy)));

@end

@implementation MONType

- (NSString *)string
{
NSMutableString * ret = [NSMutableString new];
[ret appendString:@"MONType"];
return ret;
}

@end

int main (int argc, const char * argv[])
{
@autoreleasepool {
id obj = nil;
if (random() % 2U) {
obj = [[NSAttributedString alloc] initWithString:@"NSAttributedString"];
}
else {
obj = [MONType new];
}
NSLog(@"Result: %@, %@", obj, [obj string]);
}
/* this tool's name is ARC, dump the leaks: */
system("leaks ARC");
return 0;
}

此程序产生以下错误:错误:发现多个名为“string”的方法,其结果、参数类型或属性不匹配

太好了,编译器正在尽其所能来防止这些问题。这意味着属性冲突可能会导致翻译错误。这是,因为当组合不平凡的代码库并且属性发生冲突时,您将需要纠正错误并更新程序。这也意味着在使用属性时,简单地将其他库包含在翻译单元中可能会破坏现有程序。

案例#2

标题.h

extern id NewObject(void);

标题.m

#import <Foundation/Foundation.h>
#import "Header.h"

@interface MONType : NSObject

- (NSString *)string __attribute__((objc_method_family(copy)));

@end

@implementation MONType

- (NSString *)string
{
NSMutableString * ret = [NSMutableString new];
[ret appendString:@"-[MONType string]"];
return ret;
}

@end


id NewObject(void) {
id obj = nil;
if (random() % 2U) {
obj = [[NSAttributedString alloc] initWithString:@"NSAttributedString"];
}
else {
obj = [MONType new];
}
return obj;
}

main.m

#import <Foundation/Foundation.h>
#import "Header.h"

int main (int argc, const char * argv[])
{
@autoreleasepool {
for (size_t idx = 0; idx < 8; ++idx) {
id obj = NewObject();
NSLog(@"Result: %@, %@", obj, [obj string]);
}
}
/* this tool's name is ARC, dump the leaks: */
system("leaks ARC");
return 0;
}

好的。这只是糟糕。我们引入了泄漏,因为翻译单元中没有必要的信息。这是泄漏报告:

leaks Report Version:  2.0
Process 7778: 1230 nodes malloced for 210 KB
Process 7778: 4 leaks for 192 total leaked bytes.
Leak: 0x1005001f0 size=64 zone: DefaultMallocZone_0x100003000 __NSCFString ObjC CoreFoundation mutable non-inline: "-[MONType string]"
Leak: 0x100500320 size=64 zone: DefaultMallocZone_0x100003000 __NSCFString ObjC CoreFoundation mutable non-inline: "-[MONType string]"
Leak: 0x100500230 size=32 zone: DefaultMallocZone_0x100003000 has-length-byte: "-[MONType string]"
Leak: 0x100500390 size=32 zone: DefaultMallocZone_0x100003000 has-length-byte: "-[MONType string]"

注意:计数可能会有所不同,因为我们使用了random()

这意味着,由于 MONTypemain() 不可见,编译器将 ARC 属性绑定(bind)到对当前 TU 可见的方法(即 string 来自 Foundation 中的声明,所有这些都遵循约定)。结果,编译器出错,我们能够在程序中引入泄漏。

案例3

使用类似的方法,我还能够引入负引用计数不平衡(过早发布或消息僵尸)。

注意:未提供代码,因为案例 #2 已经说明了如何实现引用计数不平衡。

结论

通过坚持约定而不是使用属性,您可以避免所有这些问题并提高可读性和可维护性。

将对话带回到非 ARC 代码:使用属性会使手动内存管理对于程序员的可读性以及可以帮助您的工具(例如编译器、静态分析)来说变得更加困难。如果程序相当复杂,以至于工具无法检测到此类错误,那么您应该重新考虑您的设计,因为调试这些问题对于您或其他人来说同样复杂。

关于cocoa - 字典的深层复制在 Xcode 4.2 中给出分析错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7770872/

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