zoukankan      html  css  js  c++  java
  • Visual Studio /analyze不好之处(一)

    分析是一种强大的VisualC++特性,可以帮助发现bug。然而,它使用了一些相当奇特的启发式方法,这使得很难决定如何认真对待它的警告。今天我们将讨论其中一种特殊的启发式方法,并展示一个案例,其中/analyze是完全错误的。这些特殊的警告大多在VS2012中修复。在我与微软分享的repro项目中,大多数错误警告都是被处理的,所以假阳性率较低。这些测试都是用Visual Studio 2010 SP1,C/C++优化编译器版本16.00 .40219.01为80×86。

    血淋淋的细节

    看看这段代码:
    int g_values[10];
    
        int GetValue1(int index)
        {
            return g_values[index];
        }

    这段代码既不好也不坏,对也不坏。这完全取决于它是如何使用的。对于“index”在范围内,它可能应该有一个断言来添加调试生成中的运行时检查,并且索引可能应该是“unsigned”或“size_t”,但它本质上没有损坏。有人可能会争辩说,由于'index'的范围可能从INT_MIN到INT_MAX,/analyze应该警告对g_values的潜在超出范围的访问,但是如果/analyze这样做了,那么它将发出大量的警告,这将是无用的。所以/analyze,没有什么有用的话,明智地保持沉默。
    这段代码是另一回事。它坏得很危险。它每次读取都超出数组的末尾,这会导致未定义的行为,通常应避免。

    int GetValue2()
    {
        return g_values[_countof(g_values)];
    }

    /analyze足够聪明来处理这个问题。它会有点失控,会发出两个警告,但安全总比抱歉好,对吧?

    warning C6200: Index ’10’ is out of valid index range ‘0’ to ‘9’ for non-stack buffer ‘int * g_values’
    warning C6385: Invalid data: accessing ‘int * g_values’, the readable size is ’40’ bytes, but ’44’ bytes might be read
    到现在为止,一直都还不错。现在事情变得很奇怪。从正确性的角度来看,这段代码与GetValue1相同。但是/analyze要求不同:
    int GetValue3(int index)
        {
            if (index == 8 )
                return 0;
    
            return g_values[index];
        }

    对这段良性的代码/分析说:

    warning C6385: Invalid data: accessing ‘int * g_values’, the readable size is ’40’ bytes, but ’44’ bytes might be read
    对与索引进行比较的值进行一些实验,可以发现/analyze似乎在思考什么。如果将“index”与一个整数进行比较,则/analyze假定这意味着您将用索引2(在本例中为索引为10)索引g_values。索引为10表示读取扩展到第44字节的第11个元素。
    如果将索引与100进行比较,如下所示:
        int GetValue4(int index)
        {
            if (index == 100)
                return 0;
    
                return g_values[index];
        }
    然后自然地/analyze假设您将索引到索引为102的g_values,因此它会发出以下警告:
    warning C6385: Invalid data: accessing ‘int * g_values’, the readable size is ’40’ bytes, but ‘412’ bytes might be read
    至少说来很奇怪。当在代码库中遇到没有解释的警告时,实际上不可能理解这些警告。只有当你开始为/analyze文章编写测试函数时,你才有希望弄清楚内部逻辑。
    下面的代码显示了/analyze跟踪索引能力的一个同样恼人的问题。
        int GetValue6()
        {
            int sum = 0;
            for (int index = 0; index < _countof(g_values) * 2; ++index)
                if (index < _countof(g_values))
                    sum += g_values[index];
                else
                    sum += g_values[index – _countof(g_values)];
    
            return sum;
        }

    index变量在数组的两倍范围内循环,但是有仔细编写的检查,以确保索引始终正确使用。尽管这段代码被证明是正确和安全的,但是/analyze仍然给出了以下两个警告,这些警告可能会导致代码在深夜无法运行。

    warning C6200: Index ’19’ is out of valid index range ‘0’ to ‘9’ for non-stack buffer ‘int * g_values’
    warning C6200: Index ‘-10’ is out of valid index range ‘0’ to ‘9’ for non-stack buffer ‘int * g_values’

    总结

    不幸的是,这些不恰当或错误的警告使/analyze更难使用。每一个警告都必须仔细分析,以确定它是对一个细微缺陷的精辟洞察,还是对/analyze内部工作机制的奇怪揭示,还是完全错误。这需要专家的知识,使C++的神秘规则看起来比较简单。
    这些警告要么被压制,要么被标记为无趣。不管怎样,这些bug都会阻止/分析除了最敬业的开发人员以外的所有人。
     
  • 相关阅读:
    彻底完全地被LINQ(2sql以及C#3.0里的一些语法)雷到了
    Windows界面设计标准
    对于大型公司项目平台选择j2ee的几层认识(四)
    用C#开发TUXEDO客户端
    提醒一下:XmlSerializer的效率比BinaryFormatter高!
    xml, oop, 云计算、web service,敏捷开发
    做了一个简单的DLINQ性能测试
    项目组的文档作风.
    RHEL 6和RHEL 7(CentOS 6和CentOS 7)恢复ROOT密码
    mysql修改root密码
  • 原文地址:https://www.cnblogs.com/yilang/p/13375950.html
Copyright © 2011-2022 走看看