IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    g++优化触发的bug一枚

    dutor发表于 2012-03-15 13:09:17
    love 0

      本菜鸟写了一个server,经长时间激烈的测试以后,终于要在测试环境供外部使用了。经过一天激烈的打包,一枚rpm终于诞生了。上传到公司的yum包仓库,当PE同学部署时遇到了问题。程序在启动过程中莫名地core掉了,屡试不爽。使用gdb查看core文件的程序堆栈,发现程序core在了一个我从来没有修改过的类的析构函数中,core的直接原因就是C/C++程序员的老朋友Segmentation fault同学。查看该析构函数,里面只做了两个操作,简单讲,就是释放对象内存的两个delete。其中一个对象是在类的构造函数中创建,另外一个对象是在其他初始化函数startup中创建。析构函数中理所当然地对这两个对象的指针进行判断,非NULL则delete。这个类很特殊,正常情况下需要调用startup进行初始化,然后作为一个持久的对象使用。也可以不进行初始化,调用其他接口,然后销毁。我使用该类的场景就属于后者。在之前的测试过程中,core dump从未发生。
      使用下面的代码简单地描述这个场景:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    class FOO
    {
    public:
        FOO() {
            p = new Object;
        }
        ~FOO() {
            if (p) delete p;
            if (q) delete q;
        }
        void startup() {
            q = new Object;
        }
    private:
        Object *p;
        Object *q;
    };
    int
    main()
    {
        FOO foo;
        return 0;
    }

      看了这个程序,各位看官想必已经知道程序是怎么挂的了。但猫腻还不仅如此,这样编译运行该程序是没有问题的:

    1
    2
    
    $ g++ test.cpp
    $ ./a.out

      但这样,就“符合预期”了:

    1
    2
    3
    
    $ g++ -O2 test.cpp
    $ ./a.out
    Segmentation fault(core dumped)

      调试该程序,查看它的汇编代码,会发现,没有使用优化选项的情况下,g++会初始化q为NULL,但在优化的情况下q就没有被初始化。
      到这里,你可能会对C++的POD(Plain Old Data)感兴趣,但本文就不做展开了,以后有机会可能会介绍下。关于POD,可以参考这里,还有这里,作一个大致的了解。
      江湖险恶,须谨言“慎行”。



沪ICP备19023445号-2号
友情链接