wenmo8 发布的文章

符号服务器允许Windows上的开发人员工具自动查找符号。他们做得很好,以至于大多数开发人员都不必担心内部机制。然而,当事情出了问题时,了解它们是如何工作的是有帮助的,事实证明,这一切都非常简单。

我对Windows符号服务器的讨论利用了我笔记本电脑上的符号服务器,用于我自己的个人项目。每当我发布一个新版本的分形极限(64位优化,多核,快速和流动的分形探索,这里的演示版本)我把符号和二进制文件放在我的符号服务器上,这样我就可以轻松地调查我收到的任何崩溃报告。这对于一个家庭项目来说似乎有点过头了,但实际上本地符号服务器只是文件的副本,以特定的方式排列以便于检索,而且设置起来很简单。对于我公开发布的可执行文件,比如UIforETW,我将PE和PDB文件发布到Google存储上的一个公共符号服务器上——详细信息在这里。

Visual C++编译器的分析功能是提高代码质量的一个好方法。它基本上是一个21世纪的“lint”来识别许多编码错误。许多错误对于程序员来说是很难看到的,但是,通过对代码进行适当的注释,/analyze的不屈不挠的眼睛将可靠地找到它们。
我最近在一个大型代码库上使用/analyze,发现了大约500个值得修复的bug。这些错误包括超出范围的读写、printf参数错误、逻辑错误等等。这些错误有可能导致内存损坏、崩溃和所有类型的意外行为。在我进行代码清理时,有几个崩溃bug咬了我的同事,因此证明了这些bug不仅仅是理论上的问题。
列出/analyze发现的所有bug,创建起来很乏味,阅读起来也很无聊。相反,我创建了示例代码来演示/analyze在哪些方面做得最好。分析工作做得很糟糕的地方会被保存到以后的文章中。

缓冲区溢出

当调用需要传递指针和缓冲区大小的函数时,很容易传递错误的大小。我看到的一些错误包括传递错误的硬编码常量、传递错误的命名常量或传递错误的缓冲区大小。在本例中,当需要_countof()时使用sizeof(),这意味着该计数是应该的两倍,并且可能存在缓冲区溢出:

void TestBufferWarnings(const wchar_t*pSource)
{
wchar_t buffer[
10];
wcscpy_s(buffer,
sizeof(buffer), pSource);
}

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

像/analyze这样的静态分析工具必须在报告警告时过于激进(导致过多的误报)和过于胆小(导致过多的误报)之间保持微妙的平衡。我不能分析这些错误,因为我不能分析这些错误。这两个警告在使用gcc生成时都会显示,但在使用visualstudio的/analyze时则不会显示。

返回局部变量地址

第一个很清楚。它与返回局部变量地址的严重错误有关。考虑以下代码:

    const char*GetName1()
{
char name[100];
strcpy_s( name, “This
isa name” );//warning C4172: returning address of local variable or temporary returnname;
}

分析是一种强大的VisualC++特性,可以帮助发现bug。然而,它有时会在不存在问题的情况下发现问题。不幸的是,这些误报,就像这里报道的那样,使/分析变得不那么有用,因为严重的错误最终会被“狼”的叫声淹没。在这篇文章中,我描述了另一个令人沮丧的误报,它展示了一个编译器完全无法理解别名的例子。