Xcode 的“构建和分析”范围是什么?会发现泄漏应该是有限的吗?

发布于 2024-08-30 09:23:44 字数 500 浏览 5 评论 0原文

它不关心这一点:

NSString* leaker()
{
 return [[NSString alloc] init];
}

我认为它足够聪明,可以检查是否有任何代码路径可以调用该函数而不释放其返回值(我通常不会以这种方式编码,我只是测试分析器)。

它将此报告为泄漏:

NSString* leaker()
{
 NSString* s = [[NSString alloc] init];
 [s retain];
 return s;
}

但不是这个:

NSString* leaker()
{
 NSString* s = [[NSString alloc] init];
// [s retain];
 return s;
}

这对我来说似乎特别弱。是不是只在本地范围内进行分析?如果该工具无法识别出这样的事情,我怎么能指望它识别出我可能犯的实际错误呢?

It doesn't care about this:

NSString* leaker()
{
 return [[NSString alloc] init];
}

I thought it would have been smart enough to check if any code paths could call that function without releasing its return value (I wouldn't normally code this way, I'm just testing the analyzer).

It reports this as a leak:

NSString* leaker()
{
 NSString* s = [[NSString alloc] init];
 [s retain];
 return s;
}

but NOT this:

NSString* leaker()
{
 NSString* s = [[NSString alloc] init];
// [s retain];
 return s;
}

which seems particularly weak to me. Does it only analyze within the local scope? If the tool can't pick up on things like this, how can I expect it to pick up on actual mistakes that I might make?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红ご颜醉 2024-09-06 09:23:44

clang 不执行任何过程间分析,至少现在还没有。即使确实如此,它也不一定能捕获这个“错误”——潜在代码路径的排列往往会呈超指数增长,这使得它实际上是不可能的。

clang 使用一组“大多数时候”有效的启发式方法。值得庆幸的是,Cocoa 内存管理规则往往相当统一,因此启发式方法适用于大多数用途。您给出的具体示例并未真正涵盖内存管理规则,但我认为大多数人(包括我自己)倾向于将您的示例分类为“您已通过 API 记录了 leaker() 负责释放返回的对象”。这本质上类似于 - (NSString *)init... 风格的方法。

clang 知道以 init... 开头的方法返回一个“未释放”的对象,调用者有责任确保它被正确释放。这构成了启发式核心的一部分 - 它不需要整个程序或过程间分析来进行大量引用计数检查 - 如果本地代码块通过 init...< /code> 方法,该本地代码块需要确保它被正确释放。当然,如果本地代码块和相关对象是 init... 方法本身的一部分,则它被相同的“规则”覆盖,因此它会出现异常。

您可能想要的是这样的:

NSString* leaker() __attribute__((ns_returns_retained))
{
 return [[NSString alloc] init];
}

这让分析器知道 Leaker() 返回一个“保留”对象,调用者负责正确释放它。虽然我还没有测试过这一点,但我强烈怀疑会在调用leaker()时检测到“泄漏”,即:

void test(void)
{
  NSString *leaked = leaker();
  // Previous line should be caught as a "leak" by clang.
}

这是 any 的不幸限制之一静态分析器,而不仅仅是clang

clang does not perform any inter-procedure analysis, at least not yet. Even if it did, it might not necessarily catch this "error"- the permutations of potential code paths tends to rise super exponentially, making it a practical impossibility.

clang works with a set of heuristics that work "most of the time". Thankfully, Cocoa memory management rules tend to be fairly uniform, so the heuristics work for most uses. The specific example that you've given isn't really covered by the memory management rules, but I think most people (which includes myself) would tend to classify your example as "You've documented via the API that the caller of leaker() is responsible for releaseing the returned object". This is essentially analogous to - (NSString *)init... style methods.

clang knows that methods that begin with init... return an 'unreleased' object, and it is the callers responsibility to ensure that it is properly released. This forms part of the core of the heuristics- it doesn't need whole program or inter-procedural analysis to do the bulk of reference count checking- if a local block of code gets an object via an init... method, that local block of code needs to make sure it is properly released. Naturally, if the local block of code, and the object in question, is part of an init... method itself, it is covered by the same "rule", so it gets an exception.

What you probably want is something like:

NSString* leaker() __attribute__((ns_returns_retained))
{
 return [[NSString alloc] init];
}

This lets the analyzer know that leaker() returns a 'retained' object, that the caller is responsible for properly releasing it. Although I haven't tested this, I strongly suspect that the 'leak' would be detected at the point where leaker() is called, i.e.:

void test(void)
{
  NSString *leaked = leaker();
  // Previous line should be caught as a "leak" by clang.
}

This is one of the unfortunate limitations of any static analyzer, not just clang.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文