Objective-C 之Static Analysis

对于iPhone开发,执行的时候检测我们都回会用instruments,但是有些时候我们可以扼杀这些于摇篮之中。不得不谈的static analysise。

这个可以build 检查可以直接执行build and analyze执行,也看样在GetInfo中在build选项中勾上,每次build都会执行。不过你会看到它在build的时候,会浪费这些分析的时间,导致build时间长。可以参考下面的。

 

The Xcode static analyzer is a great complement to other techniques for finding bugs in software, such as unit testing. You should always use these in conjunction with the static analyzer to ensure your code contains as few bugs as possible before shipping the final product to your customers.

The following are three important issues with static analysis:

Static analysis doesn’t find every code flaw. Just like most software, static analysis tools go through constant improvement. Therefore, it may not find all flaws in your code. You shouldn’t rely on static analysis alone to ensure that your code is free of problems.
Static analysis produces false positives. False positives are unlikely problems in source code that the analyzer identifies as problems. Source-code annotations help reduce false positives.
Static analysis increases build time. Static analysis takes more time than compilation because of the deep code analyses and policy adherence checks performed. Using a build configuration tailored for static analysis lets you perform static analysis at times when fast build times are not critical.

 

 

Memory-Management Checks

in the Cocoa reference-counting model, when your code obtains an object through a method whose name starts with alloc or new, or contains copy, your code inherently has ownership of the object. When your code receives an object from a method that doesn’t return an object owned by the caller, you claim ownership of the object by invoking its retain method. At some point, the owner of the object (or a proxy for the owner) must relinquish ownership by invoking its release method. Otherwise, your code leaks the object and the memory it uses. A number of such leaks can cause your application and, potentially, the operation system to become memory starved. The static analyzer checks that your code releases the objects that it owns to avoid memory leaks.

Note: The static analyzer’s ability to detect memory leaks does not preclude you from performing leak checking on the running applications, using tools such as Instruments.

 

下面是分别对应不同的framwork的属性标识。

In cases where it would be inconvenient to rename you methods, you can use source-code annotations (in the form of macros) that specify that the object a method returns is owned by the caller. These macros are NS_RETURNS_RETAINED and CF_RETURNS_RETAINED for Cocoa-based and Core Foundation–based code, respectively.

在头文件看到

#if defined(__clang__)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#else
#define NS_RETURNS_RETAINED
#endif

我们可以这样用

- (id) obtainAnObject:(NSString *)objectID        NS_RETURNS_RETAINED ;

这样可以告诉caller,让他去release计数。这个在analyze的时候,如果你的代码call了这个函数,而自己不去释放,那么就会给出analyse提示。

 

Suppressing Static Analyzer Messages

这个简单,直接贴代码。。。

Listing 9-3  Analyzer message from a false flow path
void loop_at_least_once() {
    char *p = NULL;
    for (unsigned i = 0, n = iterations(); i < n; i++) {
        p = get_buffer(i);
    }
    *p = 1;                                => Dereference of null pointer
}
Because the analyzer analyses one method as a single entity (it doesn’t analyze called methods), it has limited information about the value of n; therefore, it has to consider the case where n = 0. To suppress the “Dereference of a null pointer” analyzer message, the code must contain an assertion that p cannot be null after the loop, as shown in Listing 9-4.

Listing 9-4  Suppressing a false analyzer flow path
void loop_at_least_once() {
    char *p = NULL;
    for (unsigned i = 0, n = iterations(); i < n; i++) {
        p = get_buffer(i);
    }
    assert(p != NULL);
    *p = 1;
}
Note: If you use custom assertion handlers, you must let the analyzer know about them using the noreturn and analyzer_noreturn attributes. For details, visit http://clang-analyzer.llvm.org/annotations.

 

Dead stores are a category of dead-code bugs: A value stored in a variable is never read. To have the analyzer ignore dead stores, use pragma directives or API attributes. Listing 9-5, Listing 9-6, and Listing 9-7 show a dead store, and how to use the unused API attribute to suppress the “Value stored to 'x' during its initialization is never read” message.

Listing 9-5  A dead-store message
int unused(int z) {
    int x = foo();                    => Value stored to 'x' during its initialization is never read
    int y = 6;
    return y * z;
}
Listing 9-6  Suppressing a dead-store message with the #pragma (unused) directive
int unused(int z) {
    int x = foo();
    int y = 6;
    return y * z;
    #pragma unused(x)
}
Listing 9-7  Suppressing a dead-store message with the __attribute__((unused)) API attribute
int unused(int z) {
    int x __attribute__((unused));
    x = foo();
    int y = 6;
    return y * z;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值