本文并非教程,算是一个清单,调试遇到麻烦可以来看看如下方法,或许可以提高debug效率。
解决方案配置
可以配置多个项目之间启动顺序、启动依赖关系、是否开启调试
配置属性->调试->命令参数,可以传入char* argv
的参数
设置运行时库MD_MT去掉运行时依赖MSVCP动态库
项目属性->配置属性->C/C++->代码生成->运行库
可以设置为多线程DLL(/MDd)或单线程DLL(/MTd),从而设置运行时软件依赖项。
函数断点
可以在没有源码的情况下,设置函数断点,可以看到什么时候调用,参数是什么。
同时可以控制重载函数进入断点。在新建断点处,加上函数名和重载函数参数,可以控制进入断点。
总之这些情况都是在使用其他第三方库时,无法取到源码的情况下。
数据断点监控内存值更改
- 添加数据中断
自动变量 右键当值更改时中断。断点界面,选择新建数据断点 - 设罝数据监控起始地址
直接写内存地址或者表达式是地址 - 设置监控的字节数
64位指针类型是8个字节
设置完数字断点,会转成内存地址,第二次调试不一定有交
多线程调试代码准备和源码中显示线程运行位置
总之就是调试状态点击暂停后,可以在调试操作栏点击在源中显示线程,可以看到线程运行位置。
并行监视和并行堆栈同时监视多线程的变量
在并行堆栈窗口可以看到多个线程的堆栈,并可以同时监视多个线程代码运行位置.
在调试->并行监视,可以看到多线程运行中的变量值,变量值可以增加删除,也可以监视表达式。
标记线程和查看所有线程运行位置
在调试->线程里打开线程窗口,可以标记线程,在调试操作栏点击在源中显示线程,可以看到线程运行位置。可以设置分组以及标记系统线程和代码线程。
可以在并行监视窗口标记线程,然后在线程窗口仅关注标记过的线程。
目的是缩小查找出问题的线程的范围,逐步发现问题所在。
条件断点使用线程号筛选进入断点的线程
设置条件断点,把条件设为筛选器,可以设置变量暂存需要筛选的线程号,并且可以设置条件表达式,筛选出符合条件的线程。
通过全部中断和线程列表定位出错代码
在调试操作栏点击全部中断,可以中断所有线程。此时看每次线程都卡在哪里,哪里就发生了死锁。
如何查明指针是否损坏了内存地址
在断点窗口新建一个数据断点,取需要观测的变量的地址,设置为更改时触发。
int main(){
char buf[16]="test practice ";
char* ptr = buf;
int i = 100;
std::cout<<"i = "<<std::endl;
//监控i数据,设置数据断点
memset(ptr, 1, 256);
std::cout<<"i = "<<std::endl;
return 0;
}
数组 buf
的长度只有16字节,而 memset
函数试图填充256字节,这会导致缓冲区溢出,产生未定义行为。这可能会覆盖 i
的值及其他未定义的行为。
正确代码如下:
int main(){
char buf[16]="test practice ";
char* ptr = buf;
int i = 100;
std::cout << "i = " << i << std::endl;
//修改缓冲区处理长度,避免溢出
memset(ptr, 1, sizeof(buf));
std::cout << "i = " << i << std::endl;
return 0;
}
函数调用很多次_在失败那次进入_断点命中次数
这个在加载场景时,经常遇到,在加载场景时,加载资源时,会调用很多次函数。
或者多个实验中,某一次实验失败。
同时多次渲染,也会调用很多次函数。
断点窗口里,可以修改命中次数,在这里可以设置第几次命中或者调用失败。
函数被调用次数很多,如何在调用失败那次进入断点?
1 调用几百次才出错,不确定条件
2 通过断点命中次数,确定第几次失败,例如命中323次,第324次失败
3 在函数开头设置断点,设置条件断点命中次数为324次
使用内存快照检查内存泄漏
内存快照部分,可以看到内存是否一直上升,且定位到一直上涨的代码。
使用内存快照检查内存泄漏
诊断工具->内存使用率->堆分析
截取快照
其实这里还可以快照cpu使用情况,可以查看哪一个函数占用cpu高,从而定位到代码,优化具体函数或逻辑,可挖掘空间很大。