Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2349607
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类: LINUX

2010-06-09 01:54:10

* 打开最高级别的编译警告选项
* 打开警告视同错误的选项

这两点是基本常识, 被人说到懒得说, 懒得听. 但现实中, 往往接手这样的项目. 理论与实践之间的差距, 在实践中比在理论中要大得多.

如果接手时已经面对成千的警告, 以上两条就别想了, 你也不能指望哪个负责任的程序员会对自己引入的编译警告认真处理, 因为他根本没机会看到哪些是他新引入的. 这种情况下, 你也有个很好的借口, 可以项目在仅仅这一个方面一烂再烂地腐朽下去. 因为最初的烂摊子不是你造成的. 此人往往已经离职, 或许还在面试新工作时把你眼下接手的项目作为重要业绩介绍给新的雇主.

集中一次性销毁所有警告, 并非不可能.

在VC 2008中做过一次, 10万行C++代码.

现在在linux下, 被迫又要做一次. 把这个过程记下来, 有几个要点还是值得注意的.

要求: 100% 保证不引入新的bug.

1. 做一次干净的build. 捕获所有的编译输出, 包括错误输出, 并把该目录备份一下
make all 2>&1 | tee make.log

2. 用grep 过滤出make.log 中所有的警告信息

3. 对警告信息进行分类, 用sort
对gcc 的警告信息略加分析, 可知, 对于如变量定义了未使用这种情况, 警告信息中会用'variable_name'这种形式嵌入一些与具体符号名有关的信息. 要用sort进行排序, 就得忽略这些信息. 我的办法是:
先给每行用数字递增编号
:%s#^#\=line('.') .  ' '
然后把所有的'...' 都替换成'', 这样所有的同类警告信息就一致了.

然后以sort -t: -k4 -u 排序, 相信这一命令的输出结果会给你带来信心: 因为警告总数虽多, 但所属类别往往有限, 我眼下正做的这个, 1000警告, 29个类别.
再根据每行的唯一标识, 把前面删除的'...'信息给还原回去. 这在参考警告进而进行修改时还是很有用的.

以上2,3的步骤, 现被我写成一个bash函数, 以sort_gcc_warning make.log 即可得到名为
sorted_warning.txt 文件, 如下:

function sort_gcc_warning()
{
    make_log="$1"
    egrep '^[^:]*:[0-9]+: warning:' $make_log | cat -n  | sed 's/^ *//;s/[ \t]\+/ /' > raw_warning.txt
    sed "s#'[^']*'#''#g" raw_warning.txt | sort  -t: -k4 > sort_warning.txt
    sort -t: -k4 -u sort_warning.txt | sed 's/^[^:]*:[0-9]\+: warning:/warning:/' | while read f; do
        echo $(fgrep -c "$f" sort_warning.txt) "$f"
    done > warning_stat.txt

    declare -a raw_warn
    while read line ; do
        eval "raw_warn[${line%% *}]"='"'"${line#* }"'"'
    done < raw_warning.txt

    sort -rn warning_stat.txt | while read f ; do
        warn="${f#* }"
        n_warn="${f%% *}"
        echo ============ $f ==============
        # First change the ' ' to ':' to make sort to use ':' as separator
        sed 's/ /:/' sort_warning.txt | fgrep "$warn" | sort -t: -k2,2 -k3rn,3 | while read x; do
            line_no="${x%%:*}"
            echo "${raw_warn[$line_no]}"
        done
    done > sorted_warning.txt
   
}

4. 每次只集中修改一类警告

这一点至关重要, 只修改一类警告, 你的大脑仅需专注于同样的一个问题, 相关的注意事项也非常有限, 你可以集中地修改所有的同类警告.

5. 修改完该类警告后, 再干净地make一次.

find -iname '*.o' | while read f; do eu-elfcmp $f ../proj_origin/$f; done

这一命令用来保证你的修改不会有误, 因为它从最终生成的二进制文件的角度保证了你消除警告的修改没有引起任何破坏.

但是, 实际情况中, 可能会出现.o在修改后被改变, 此时就需要单个地对修改的文件重点review了, .o被改变并非绝对不能容忍, 只是需要加倍小心.

我实际操作过程中, 目前为止, 让我吃惊的是, 修改后引起.o改变的情况并不多. 也只有这样, 人工review每处修改才是可能的.

6. check in

7. 重复步骤4-6, 直至所有警告全部消除.

对上次在windows上的C++项目做这一过程, 大致也是用vim等工具对build log做分类处理. VC的特殊情况是, 每个警告有个唯一的数字编号, 可以用来分类同类警告. 而在linux上, 多出 eu-elfcmp这个工具, 让整个过程做起来信心大增. eu是end user的简称. 用来比较两个elf格式的文件的.
阅读(1173) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~