这是今天下午帮同事查的一个客户端 C++ 的 bug,前人留下的谜之代码。。

具体情况是,客户端实现了有一个简单的内存池,每次申请内存的时候会把新申请到的内存信息存到一个 map 里,据说是为了检查内存泄漏。

大致是像下面这段代码

 std::map<unsigned long, int> m;

 template<typename T>
char* jnew(int count)
{
char* p = new char[sizeof(T) * count];
if (count == )
m[(unsigned long)p] = ;
return p;
}

同事把第 7 行注释掉了,结果客户端就开始崩溃。神奇哟~

报错信息中有 0x00000005 字样,显然是空指针的问题,断点第 8 行,查看 count,是个很大的数,进入到 map 的代码里,看到果然里面的指针全他妈是空的,似乎没有被初始化。

然后我取消注释,断点第 7 行,和第 1 行。

程序启动,进入到第 7 行的断点,count 很大,continue,又在第 7 行停下来,count 还是很大。

于是取消第 7 行断点,继续断第 8 行,continue,

啪!停在了第 1 行!基本证实了是初始化的问题。就是最初 count != 1 时访问到 m,m 还没有被初始化,然后崩溃。

那么可以推断,程序第一次调用 jnew 的时候,是在初始化另外一个全局变量或者静态变量。

然后查看调用堆栈,果然是在一个类的静态成员两变量初始化中。

同事感叹,印象中只是在某本书上见过类似的问题,没想到今天自己遇上了。

重现一下车祸现场:

简单说就是,如果有两个全局变量 a 和 b,a 和 b 分别在两个文件中,a 的初始化又依赖 b,那么就有可能 a 初始化的时候 b 还没又被初始化,导致程序崩溃

nofuck.cpp

 #include <map>

 static std::map<int, int> m;

 std::map<int, int>& GetMap()
{
return m;
}

main.cpp

 #include <map>

 std::map<int, int>& GetMap();

 class Fuck{
public:
Fuck(){
GetMap().clear();
}
}; static Fuck fuck; int main(int argc, char** argv)
{
return ;
}

解决方法是,把 static std::map<int, int> m; 放到 GetMap 函数内部。

这一类 bug 的特征是,在进入 main 函数之前程序就挂掉。

最后,还是那个原则,全局的东西能不用的尽量不用。

参考链接

http://stackoverflow.com/questions/1005685/c-static-initialization-order

http://coolshell.cn/articles/10115.html

一个可遇不可求的 bug 全局变量初始化顺序问题 哈哈的更多相关文章

  1. 输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数

    题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次. 分析:首先最先想到的是遍历从1到n的每 ...

  2. 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。

    题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0. 解法一:暴力求解.从1开始查找M,然后判断M*N=X这个数字是否只含有0,1. 解法二:由 ...

  3. 怎样才能提交一个让开发人员拍手叫好的bug单

    怎样才能提交一个让开发人员拍手叫好的bug单 软件测试人员写得最多的文档就是测试用例和BUG,现在测试用例和BUG都没有标准的模板,每个公司使用的缺陷管理工具都有可能不一样,如果你换了一家公司就有可能 ...

  4. 可遇不可求的Question之导入mysql中文乱码解决方法篇

    可遇不可求的Question之导入mysql中文乱码解决方法篇 先 set names utf8;然后 source c:\1.sql ?

  5. 编写一个ComputerAverage抽象类,类中有一个抽象方法求平均分average,可以有参数。定义 Gymnastics 类和 School 类,它们都是 ComputerAverage 的子类。Gymnastics 类中计算选手的平均成绩的方法是去掉一个最低分,去掉一个最高分,然后求平均分;School 中计算平均分的方法是所有科目的分数之和除以总科目数。 要求:定义ComputerAv

    题目: 编写一个ComputerAverage抽象类,类中有一个抽象方法求平均分average,可以有参数. 定义 Gymnastics 类和 School 类,它们都是 ComputerAverag ...

  6. 【C语言】输入一个整数N,求N以内的素数之和

    [C语言]输入一个整数N,求N以内的素数之和 /* ========================================================================== ...

  7. 算法题:给你一个自然数N,求[6, N]之内的全部素数中, 两两之和为偶数的那些偶数。

    /* 算法题:给你一个自然数N,求[6, N]之内的全部素数中. 两两之和为偶数的那些偶数. */ #include <iostream> using namespace std; voi ...

  8. Java中,一个存在十几年的bug...

    今天,分享一个JDK中令人惊讶的BUG,这个BUG的神奇之处在于,复现它的用例太简单了,人肉眼就能回答的问题,JDK中却存在了十几年.经过测试,我们发现从JDK8到14都存在这个问题. 大家可以在自己 ...

  9. 面试题(造火箭必备技能):请举例一个最有成就感的性能bug

    当前,绝大部分招聘都有性能要求或者把其作为加分项(会性能优先),哪怕你不是面试的性能,面试的时候可能会问性能,所以大家才会有"面试造火箭,进去拧螺丝"的共鸣.至于企业为什么重视性能 ...

随机推荐

  1. Java笔记一JAVA安装环境变量配置

    window系统安装Java 下载Java开发工具包JDK,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.htm ...

  2. Java执行shell遇到的各种问题

    1.判断子进程是否执行结束 有的时候我们用java调用shell之后,之后的操作要在Process子进程正常执行结束的情况下才可以继续,所以我们需要判断Process进程什么时候终止. Process ...

  3. 关于six.with_metaclass(ABCMeta, object)的理解

    在学习Python过程中,看到了生成虚基类的方式, class PeopleBase(six.with_metaclass(ABCMeta, object)): @abstractmethod def ...

  4. 一分钟搭建Spring Boot

    1.首先你的电脑需要安装jdk.Apache Maven.Intellij IDEA 2.新建项目  (敲重点,有的同学有没有Spring Initializr 这个请到本文章后面看安装步骤) 3.选 ...

  5. 微信小程序--动画animation

    js: list:[], contentflag:false   this.animation = wx.createAnimation({ duration: 500, timingFunction ...

  6. SpringJDBC :jdbcTemplate在连接是出现 org/springframeworkbc/core/JdbcTemplate : Unsupported major.minor version 52.0 异常解决

    原因是这个在jdk9版本才能使用,需更新jdk版本. 更新jdk9之后在idear的配置: 第一步:File---->Project Structure---->Project 第二步: ...

  7. AS3中的单件(Singleton)模式

    单件(singleton)模式在c#中是最容易实现的模式,其主要用意就在于限制使用者用new来创建多个实例.但在as3中,构造函数必须是public的(语法本身要求的),而且也不能在构造函数中抛出异常 ...

  8. 数据库类型空间效率探索(五)- decimal/float/double/varchar

    以下测试为userinfo增加一列,列类型分别为decimal.float.double.varchar.由于innodb不支持optimize,所以每次测试,都会删除表test.userinfo,重 ...

  9. Mysql 提升大数据表的拷贝效率

    工作上会经常遇到量级比较大的数据表  :场景: 该数据表需要进行alter操作 比如增加一个字段,减少一个字段. 这个在一个几万级别数据量的数据表可以直接进行alter表操作,但是要在一个接近1000 ...

  10. RN与webview通讯

     一.RN给webview发送信息 this.webview.postMessage(message) 二.监听从React Native发过来的消息: window.document.addEven ...