一个可遇不可求的 bug 全局变量初始化顺序问题 哈哈
这是今天下午帮同事查的一个客户端 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 全局变量初始化顺序问题 哈哈的更多相关文章
- 输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数
题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次. 分析:首先最先想到的是遍历从1到n的每 ...
- 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。
题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0. 解法一:暴力求解.从1开始查找M,然后判断M*N=X这个数字是否只含有0,1. 解法二:由 ...
- 怎样才能提交一个让开发人员拍手叫好的bug单
怎样才能提交一个让开发人员拍手叫好的bug单 软件测试人员写得最多的文档就是测试用例和BUG,现在测试用例和BUG都没有标准的模板,每个公司使用的缺陷管理工具都有可能不一样,如果你换了一家公司就有可能 ...
- 可遇不可求的Question之导入mysql中文乱码解决方法篇
可遇不可求的Question之导入mysql中文乱码解决方法篇 先 set names utf8;然后 source c:\1.sql ?
- 编写一个ComputerAverage抽象类,类中有一个抽象方法求平均分average,可以有参数。定义 Gymnastics 类和 School 类,它们都是 ComputerAverage 的子类。Gymnastics 类中计算选手的平均成绩的方法是去掉一个最低分,去掉一个最高分,然后求平均分;School 中计算平均分的方法是所有科目的分数之和除以总科目数。 要求:定义ComputerAv
题目: 编写一个ComputerAverage抽象类,类中有一个抽象方法求平均分average,可以有参数. 定义 Gymnastics 类和 School 类,它们都是 ComputerAverag ...
- 【C语言】输入一个整数N,求N以内的素数之和
[C语言]输入一个整数N,求N以内的素数之和 /* ========================================================================== ...
- 算法题:给你一个自然数N,求[6, N]之内的全部素数中, 两两之和为偶数的那些偶数。
/* 算法题:给你一个自然数N,求[6, N]之内的全部素数中. 两两之和为偶数的那些偶数. */ #include <iostream> using namespace std; voi ...
- Java中,一个存在十几年的bug...
今天,分享一个JDK中令人惊讶的BUG,这个BUG的神奇之处在于,复现它的用例太简单了,人肉眼就能回答的问题,JDK中却存在了十几年.经过测试,我们发现从JDK8到14都存在这个问题. 大家可以在自己 ...
- 面试题(造火箭必备技能):请举例一个最有成就感的性能bug
当前,绝大部分招聘都有性能要求或者把其作为加分项(会性能优先),哪怕你不是面试的性能,面试的时候可能会问性能,所以大家才会有"面试造火箭,进去拧螺丝"的共鸣.至于企业为什么重视性能 ...
随机推荐
- JSONObject.fromObject--JSON与对象的转换
1. List集合转换成json代码 List list = new ArrayList(); list.add( "first" ); list.add( "secon ...
- 打开控制台F12弹出弹窗
window.onload=function(){ document.onkeydown=function(){ var e=w ...
- springboot @scheduled 并发
本文介绍如何使用springboot的sheduled实现任务的定时调度,并将调度的任务实现为并发的方式. 1.定时调度配置scheduled 1)注册定时任务 package com.xiaoju. ...
- IO 、NIO、AIO
Java 中的流 https://ifeve.com/java-nio-vs-io/
- SpringCloud Feign context-path踩到的坑
最近在使用SpringCloud的context-path时,遇到了一些坑,记录一下. server.context-path(上下文) 服务提供者的application配置文件中有一个属性叫ser ...
- python爬虫小说代码,可用的
python爬虫小说代码,可用的,以笔趣阁为例子,python3.6以上,可用 作者的QQ:342290433,汉唐自远工程师 import requests import refrom lxml i ...
- 20175314 《Java程序设计》迭代和JDB
20175314 <Java程序设计>迭代和JDB 要求 1 使用C(n,m)=C(n-1,m-1)+C(n-1,m)公式进行递归编程实现求组合数C(m,n)的功能 2 m,n 要通过命令 ...
- 89. Gray Code返回位运算的所有生成值
[抄题]: The gray code is a binary numeral system where two successive values differ in only one bit. G ...
- GitHub下载子目录
背景 整个Github目录太大,国内网速不好,且其他部分也不需要. 方法 把 /tree/master 改成 trunk. svn checkout https://github.com/lodash ...
- eclipse中集成python开发环境
转载:https://www.cnblogs.com/mywood/p/7272487.html Eclipse简介 Eclipse是java开发最常用的IDE,功能强大,可以在MAC和Windos上 ...