我的BUG日记

记录职业生涯中遇到印象深刻的BUG:

1. win32网络编程中,发送和接受所用的缓冲区大小不同,导致recv函数必须调用多次才能接收完毕,详情见:

http://blog.csdn.net/qq_33826977/article/details/78191412

2.在一次关于装饰者模式的UI判断中,由于之前的结构体的某个成员变量没有初始化变成垃圾值,导致函数中判断的值永远为FALSE

3. 当创建了win32项目,却使用了console风格的类函数时,报一个  winmain  的链接错误

    解决方法是在项目属性,C/C++中修改属性

4.有一次调用node.lib时,报错node.lib不完整,搞了很久之后, 发现用npm默认下载node.lib的网络连接有问题,总是没法下载到完整的lib文件

   解决办法就是自己去官网下载,再替换掉。

5.打开一些vs项目时会因为vs版本不同而报错,比如说VS2013 对应的是 120

6.在使用一个日记类的时候,其逻辑是,新开一个线程专门讲sstringstream中的内容追加到文件中,主线程负责追加到内容到sstringstream中,通过event和锁的机制来保证读写一致:

 

int main()       
{ 
	FileLog filelog("log.txt");		
	filelog.Start();			//此时开始新线程
	std::ofstream ofs;
	//Sleep(2000);
	myBaseFilelog.AddString("kkkkkkkkkk");
	myBaseFilelog.AddString("88888lllllllzzzzzzzzzzzzzzzzzzzz5555");
}

 

 

 

 

发现并没有意料中的结果。

 

问题的根源是: 主线程很快就退出了,而子线程可能还没开始运行——多线程的问题果然得考虑到先后机制啊!

目前比较挫的办法就是中间加个Sleep.

7. 使用std::wcout读取unicode文本并且输出到控制台时,发现一旦读取到 “©” 这个字符,后面的字符再也无法输出,代码如下:

 

        std::wstring  str = TEXT("我没想到");
	wcout.imbue(locale("", LC_CTYPE));
	wcout << str << std::endl;

	
	ifstream fin;
	fin.open(TEXT("C:\\Users\\admin\\Desktop\\test.ini"), ios::binary);
	// 跳过unicode文本开头有两个字节0xFFFE(称作BOM,用于标识unicode编码)
	fin.seekg(2, ios::beg);
	while (!fin.eof())
	{
		wchar_t wch, wch2 = TEXT('©');
		fin.read((char *)(&wch), 2);
		//cout << wch <<" "<< *((&wch) - 1)<<endl;
		if (wch != wch2)
		{
			//cout << "don;t equal" << endl;
			wcout << wch;
		}
		else
		{
			//wcout << "equal ©" << endl;
			wcout << wch;
		}
		
	}

通过

wcout.imbue(locale("", LC_ALL));
wcout << wch;
wcout.imbue(locale("", LC_CTYPE));

可以改变,但是仍然无法输出“©”,而是输出了问号

 

 

8.读取unicode文本,到达EOF时老是会把读取末尾的字符2次

问题根源:在进行read操作时,即使读取了字符文件末尾,都是还没有到达EOF,所以eof判断为假,再读一次,到达了EOF,没有读到内容,所以存储变量仍然是之前的内容,那么就会得到2次的结果。所以最好的方法是操作之前判断它有没有读取成功。

 

while (!fin.eof())   //std::ifstream fin;
	{
		fin.read((char *)(&readChar), 2);
		if (fin.good())
		{
			//do something
		}
		else  // fin.bad()  , 避免EOF时读取到末尾字符2次的情况
		{
			//do something
		}
	}

 

 

 

 

 

9.读取文本时发现了不能稳定出现的BUG,可能会有中断,或者断言,或者crash,或者正常运行
问题根源: 不能稳定出现,往往和内存有关系,问题代码如下:

 

wchar_t* sDes = new wchar_t();
std::wstring value = L"";
int len;
if (GetValue(iKey, sDes, len))
{
	for (int i = 0; i < wcslen(sDes); i++) 
	{ 
		value = value + *(sDes + i);
	}
	return value;
}

 

 

GetValue函数对  *(sDes + i)  [即传入指针的后续内存]进行了赋值操作。

 

 

因为我们传入的只是一个char类型指针,那么它内存后面的数据和空间都是未知的,也就是随机的。所有是一个不稳定的BUG。

所以尽量使用wchar_t sDes[100] = { 0 };

申请一片连续的内存,再传入首地址。
 

10. new和delete一定要成对出现,不要再犯内存泄漏的毛病!!!

 

11.在vs下遇到了LNK 2001错误,问题根源是: 在类的头文件中声明了静态成员变量,但是在实现文件中没有定义。

又或者是头文件有函数声明,但是实现文件没有写相应的函数定义。


12.在进行一个定时器的设置时,由于传入一个TimePoint ,  比当前时间早,相比较为负数,又因为时间间隔参数声明为uint_64, 导致加上负数溢出变成了一个奇怪的数值

    解决方法: 在相加之前将uint强转成int, 先比较一下是否会变成负数,再进行后续操作

13.在windows实际工程项目的编程中,写了一个处理文件数据的单例类,键值对存储在map中,读取文件之后是正常的,在别的模块中再去读取该map容器的数据时发现map的size为0!!

问题根源: 首先通过断点调试发现,存在了2个不同的该类的对象(可以看到this指针不一样),问题的根本是这样一个普通定义的类,在每个模块中都可以生成这样的一个对象的。那么每个模块都有自己对应的一个对象,都无法实现文件读取到的数据共享了。我们这里的意图是有一个数据全局(所有的小模块)共享的单例类。应该把其声明为DLL导出类。

 

14.在某个地方加入了一个头文件,把以前的头文件的代码复制进来,结果报了一大堆链接错误。——没理由啊,之前都没问题的呀?

问题根源:之前的头文件有 #include "stdafx.h", 但是在新的当前目录下没有stdafx.h, 所以找不到,随后来一堆的链接错误。要好好查看错误的根源,一切错误都有问题的根源,好好看编译器的报错提示是最好的debug方式。

 

15.之前是由公共库提供头文件和编译好的lib和dll, 后来接到一个任务就是把源代码拿过来,自己建一个模块,以后依赖于这个模块而不是依赖于别人给的DLL。后来发现有2个控件没有正常绘制出来(它们在UI界面上,可以点击,hover, 但是不可见,而且水平方向的右边的圆形logo也被遮住了绝大部分,被水平截断)

后来组长告诉我,把我新加的UI库换成旧的就没问题了。   于是就去找原因,(第一天下午)首先确定图片的ID,然后去找图片的绘制流程,由于在UI上绘制的图片太多了,虽然使用了条件断点(判断是否绘制这2张图片),但是它确实进入了绘制函数(之前还因为一次断点的跳动比较异常,以为是没有进入绘制函数),DrwaFrmImg---------绘制拉伸的图片(当时没注意到这个细节)。这个方向似乎找不到什么线索,就又看到2种方式生成的DLL和lib,发现2个DLL的大小差别(都是debug版本)竟然达到一倍。(第二天上午)使用了dumpbin工具分别去查看lib和dll,虽然dll(数据段位置和大小,后面再研究)有一些差别,但是并看不出什么实质性的东西。于是就去探索旧的库生成DLL有什么不同之处,就盯着这个DLL为什么是700多KB,而我自己拿着这个源代码才生成的358KB的代码。发现这个库依赖于2个库Base, Ev, 但是在UI库中并没有使用到Ev库的东西,就想不通为什么会依赖于Ev库。又往这个错误的方向走了几步,后来组长让我把Ev库删掉,一样可以生成700多KB的dll,说明和该Ev库没有关系,那个依赖关系可能是人为加入的。于是并且把其他的没有关系的库都删掉,保留一个纯净的UI库。最后发现跟其他模块都没有什么联系,于是就对比新旧的2个库,后来组长提供了思路——要么把好的玩成坏的,要么把坏的玩成好的,(第二天下午)于是我就尽可能修改我新加入的UI库,(之前因为编译不通过的原因做了不少改动),一直往旧的库靠近,最后修改了很多,发现终于好了,我以为是我为了避免那种头文件互相依赖什么的编译错误,做的改动弄错了,现在弄回来了,应该是这个问题,和一个冲突的枚举变量 Ctrl4State 有关系(控件嘛) 准备提交,给组长来了当头一棒,并没有找出问题的根源。让我把改动一个一个回滚,找出问题的根源——对啊,BUG怎么可以不知不觉地就能好,所有的问题都是有根源的。于是我就一个一个改动回滚(我是线性回滚的,后来发现这是一个错误的做法,我因为用二分法回滚的),最后重重艰难之下,(第二天晚上)找到了问题的根源, 绘制的时候使用的一个代表图片的的结构体:

 

struct FrmImgInfo

构造函数中调用的置位函数:

 

void Reset()
{
	ImgInfo::Reset();
	//正常的代码
	double fZoomX = GetAppZoomX();
	//有BUG的代码直接等于6
	szTCorner.cx = (LONG)(8 * fZoomX);
	szTCorner.cy = (LONG)(8 * fZoomX);
	szBCorner.cx = (LONG)(8 * fZoomX);
	szBCorner.cy = (LONG)(8 * fZoomX);
	bStretch = true;
	bStretchMid = true;
};

 


哎呀,我去,果然,90%的bug都来源于低级错误!!!不过也幸好找出来了。有问题的代码是跟一个隔壁组的同学拿的,而正确的代码是组长发的。。同一个代码的不同版本,囧= =  哎。。。整整烧了我一天。。。

 

 

 

 

16.今天在一个lib模块中include另外一个lib模块的头文件时,使用该头文件的函数,总是对该头文件的函数报错 “无法解析的外部符号”,后来发现了————是因为调用一个lib模块的函数,导入头文件,所以一直可以声明有这样一个函数,不过没有导入静态库,所以一直无法找到该函数的定义,要么使用#pragma comment(lib,"xxx.lib"),要么在项目属性中设置 (dll是链接器,lib是库管理器)的常规-附加依赖项中加入该库,就不用显式代码加入lib。足足浪费了差不多2个小时,以后记住这个无法解析的外部符号,往往是因为找不到这个函数的定义导致的,


17. win32常用的CreateWindow函数,有一个参数是hwndFather, 如果没有给窗口风格指明WS_CHILD的话,那么这个参数就会变成所有者窗口——这是不一样的。因为如果父窗口不是visible, 子窗口是一定不可见的。要注意所有者窗口和父窗口

 

18.在进行多个嵌套子窗口的开发中,发现一个正在输入的编辑框在窗口动态调整大小(编辑款换行)的过程中,编辑框的背景残留着之前的背景,发来发现原因是::SendMessage和::PostMessage导致的绘制顺序先后的问题

19.在给定矩形内绘制文本,先判断矩形的宽度是否大于文本的宽度,再进行绘制。但是发现两位数的数字,只绘制了十位,各位不见了。——后来发现,是因为我们使用GDI+的绘制,更换成GDI绘制就没有问题。在同一个窗口绘制文本时,GDI+和GDI混用可能会有问题,GDI+尽量不要用来绘制文本。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值