老司机找bug的十年心路历程

一.码畜:靠编译器帮自己查语法错误

消灭笔误:编写适合程序员的键盘练习

if (常量==变量或表达式)

使用goto接力超长的if,switch

连续的if还是if elseif

多个条件的组合:精心的排版

多重括号的匹配

条件编译

各种const:不要纠结各种常量了,这个世界上唯一不变的就是变化。用APIWriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

 

查看宏展开后的.i文件:VC编译选项加/EP /P(项目、属性、配置属性、C/C++、预处理器、预处理到文件:是,预处理取消显示行号:是),重新编译,查看宏展开后对应的.i文件。gcc加-E

 

偶遇到莫名其妙的编译错误都是用“每次用/*...*/或#if 0...#endif注释掉不同部分再重新编译,直到定位到具体语法出错的位置。”的方法解决的。

 

附加包含路径、附加库路径、附加依赖库的设置。

 

二.码农:靠调试器帮自己查逻辑错误

for/while语句后多余的分号

while/do while语句在语义上的歧义

条件断点

消息断点

数据断点

__asm int3或DebugBreak()断点

在内存窗口中观察数据的原始字节形态

 

Call Stack:崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处,看不懂时双击下一行,直到能看懂为止。

 

“给定一个小点的输入,完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门!

递归函数关注以下几个因素

·退出条件

·参数有哪些

·返回值是什么

·局部变量有哪些

·全局变量有哪些

·何时输出

·会不会导致堆栈溢出

语法糖越甜,编译调试查错越苦!

C++的隐藏调用:单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。

 

任务管理器、VMMap、Process Monitor、Process Explorer、GDI泄露检测工具、……

 

三.码人:靠写日志帮自己查运营错误

CrashDump或Core的无力。

PDB的无力。

线上Debug的无力。

观察复杂数据的无力。

多线程调试的无力。

调试时序高度依赖代码的无力。

调试万年一遇非法数据的无力。

 

有时不将“调用函数名字+各参数值,进入函数后各参数值,中间变量值,退出函数前准备返回的值,返回函数到调用处后函数名字+各参数值+返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的,包括捕获各种异常、写日志到屏幕、单步或设断点或生成core或dmp文件、……这些方法都不行!

 

四.码神:靠冥想和顿悟帮自己查不可再现错误

假死的各种原因:

·控制循环的变量的取值范围有符号/无符号,==/<=

·控制循环的变量没变

·控制循环的变量被外部程序修改

·各种资源泄露

·死锁

·网速变慢或网络资源耗尽或网络时通时断

·权限、UAC、杀毒软件实时防护

·操作系统或软件自动升级

·以为系统时间不可逆

·以为系统时间相关变量不会溢出(GetTickCount()约49.7天就归0了!)

·……

不要企图优雅的结束(因为这是不可能办到的)

而要在烂的不能再烂的摊子上也能重整河山!

Python正确的学习路线,你一定不知道的薪资翻倍秘诀

如何从8K提至20K月薪,你要掌握学习那些技能

  • qq_32250025集中营: 赵老师,遇到一个问题,很诡异。TerminateProcess结束一个控制台进程,代码运行正常。在任务管理器上看到“应用程序”还在,“进程”已经找不到了。搜索进程ID,确实找不到该进程了。为啥应用程序没有关闭呢?[cpp] view plain copy
    1. bool BackstageCore::KillProgress(const DWORD& _dwId)  
    2.  {  
    3.   HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, _dwId);//通过这个函数判断进程是否活着,不准确  
    4.   if (nullptr == hProcess)  
    5.   {  
    6.    std::cout << "进程的句柄为空!ID = " << _dwId << std::endl;  
    7.    return false;  
    8.   }  
    9.   else  
    10.   {  
    11.    DWORD dwExitCode = _dwId;  
    12.    ::GetExitCodeProcess(hProcess, &dwExitCode);  
    13.    BOOL bres = ::TerminateProcess(hProcess, dwExitCode);  
    14.    if (bres == 0)  
    15.    {  
    16.     std::cout << "杀死进程出异常:ID = " << _dwId << " 错误码:" << GetLastError() << std::endl;  
    17.     return false;  
    18.    }  
    19.    ::CloseHandle(hProcess);  
    20.   }  
    21.   return true;  
    22.  }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值