zoukankan      html  css  js  c++  java
  • vc++调试总结

    .在debug->windows下,有以下调试窗口
    1)Breakpoints管理断点信息
    可以新建条件断点,函数断点,以及特定地址改变断点(用于检测数据发生改变时机点)
    在断点处,可以进入汇编语言查看汇编信息
    断点详细信息包括: condition, hit count, funcion, file, address, process 等详细信息
    2)Memory 给出了内存地址上详细信息,可查看各种变量,结构体,类等内存状态
    3)Registers 给出了寄存器相关信息,在调试汇编时可以查看寄存器信息
    4)Processes 给出进程相关信息,包括 ID, path等
    5)Moudules 给出了调用模块列表,一般控制台程序会调用如下模块:
    ucrtbased.dll
    vcruntime140d.dll
    KernelBase.dll
    kernel32.dll
    ntdll.dll windows内核提供的所有原生API基本都是从该库中导出
    6)Threads 给出了当前进程的所有线程信息,一个空的控制台程序包括一个主线程及多个工作线程,
    其中,三个工作线程均来自于 ntdll.dll,在 Location 处,通过展开调用栈可以查看线程具体信息
    7)CallStack 给出了程序调用栈信息,根据调用栈可以进行调用回溯
    8)Watch 可查看变量值,也可以修改变量值继续调试,变量值可以用10进制或者16进制显示
    .程序调试过程中,可以拖动调试点重新执行已经执行过代码,方便问题查找与确认
    .#include <assert.h> assert() function可以检测一些断言错误,调试assert方法如下:
    1)使所有断点无效
    2)debug 程序,程序会提示断言错误,点击重试即可定位错误
    3)如果不调试而直接运行程序,断言错误仍旧会被抛出,但是无法进入代码查看更加具体信息
    .编辑并继续执行
    1)设置 c/c++->General->Debug Information Format = Program Database for Edit And Continue
    2)设置 Linker->optimaization->References = No(/OPT:NOREF)
    3)将断点拖拽至待继续执行代码前
    4)修改待继续执行代码,继续调试即可应用编辑后代码
    .GetLastError() 返回上次执行函数的返回值,在 Tools->Error lookUp 下可查看错误对应的具体信息
    同时,在监视窗口中输入 err 或 err,hr 可查看上次返回值情况
    .在监视窗口(watch)中,可以使用 sizeof 运算符计算结构体,数组等大小信息
    .x86架构为小端存储,对于unicode编码,如 t=0x0074, 在内存地址中则存储为 74 00,其实小端存储更加符合计数规则
    .相同成员变量的类与结构体在内存空间表示是一致的,调整成员变量顺序可以优化内存占用,规则如下:
    将变量按占用空间从小到大排列,可以最大化优化内存占用(基于结构体对其原则)
    .内存泄漏调试
    1)引入以下语句
    #define _CRTDBG_MAP_ALLOC // 必须在包含crtdbg.h前预定义该宏,使得malloc函数重定义
    #include <crtdbg.h> // 用于c运行时库的调试,不包含 new 运算符重定义
    #ifdef _DEBUG
    #define new new(_CLIENT_BLOCK, __FILE__, __LINE__) // 重定义 new 运算符
    #endif
    2)在程序入口点设置内存泄漏检测
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF);
    3)在程序结束处输出内存泄漏
    _CrtDumpMemoryLeaks();
    4)注意,仅在调试模式下可以定位泄漏,关闭程序后 output 窗口大致给出如下信息
    Detected memory leaks!
    Dumping objects ->
    d:debugpracticepracticepractice.cpp(19) : {87} normal block at 0x013B78D8, 100 bytes long.
    Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
    d:debugpracticepracticepractice.cpp(18) : {86} client block at 0x015B5040, subtype 0, 1048576 bytes long.
    Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
    Object dump complete.
    双击提示信息,即可进入内存泄漏点
    5)根据 4)给出的提示信息,在第 86,87 次分配中存在内存泄漏,在程序开始处添加 _CrtSetBreakAlloc(86),
    再次调试运行程序,程序将会在第 86 次分配内存前停下,内存泄漏位置定位成功
    .定位堆内存破坏(调试模式下)
    1)在调试模式下,堆内存分配会在分配内存空间后边增加一些调试信息,
    如 char *p= new char[2] 在内存中表示为 cd cd fd fd fd fd ...,
    当delete []p 调用时,程序会检测 fd fd fd fd 是否发生改变,如果发生改变则提示堆内存错误。
    2)在 Release 模式下, 程序不会添加附加信息,因此不会检测堆内存被破坏错误,
    但是在 Release 模式下,由于没有 fd fd fd fd ... 形式的缓冲区,程序越界改写数据可能导致一些奇特的且不固定的错误!!!
    3)在调试模式下,检测堆内存破坏可使用数据断点(Data Breakpoint),这里可以设置 p + 5 数据发生改变后触发断点,
    然后在调用堆栈中即可定位错误,注意,数据断点设置需要获得数据所在的准确内存地址(即数据指针有效后方可设置该数据相关的数据断点)
    .定位堆内存破坏(Release模式下)
    1)在 Release 模式下,使用 devenv.exe 启动调试,当操作系统为程序分配堆内存时,在其后邻接位置分配保护内存,利用检测保护内存触发越界。
    2)在注册表 计算机HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution Options 下增加调试应用程序 x.exe。
    3)增加如下选项 Debugger(REG_SZ)=C:Program Files (x86)Microsoft Visual Studio 14.0Common7IDEdevenv.exe
    GlobalFlag(REG_SZ)=0x02000000 PageHeapFlags(REG_SZ)=0x2
    4) 点击 x.exe 启动调试器,当前调试器好像只能在堆内存释放时定位问题,与预期不太一致?代码如下:
    char *p = new char[5]; memcpy(p, "123456", 6); delete[]p;
    5)要定位到源码,需要保证 .pch 及源码文件路径未发生改变
    .栈破坏可以使用数据断点进行监测, 设置数据断点,当触发了预期以外的断点,则表示该栈数据被破坏,
    同样,该方法也适用其他任何数据破坏的监测。

  • 相关阅读:
    关于添加类目
    关于协议传值
    Block传值
    UIImagePickerController(相册的使用)
    Handler(单例传值)
    UISearchController
    org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.microsoft.sqlserver.jdbc.SQLServerDriver '
    vs2015 打开项目自动运行 npm install
    Apktool下载与安装 windows环境
    React-Native 问题随记2: com.android.builder.testing.api.DeviceException
  • 原文地址:https://www.cnblogs.com/luofeiju/p/15387124.html
Copyright © 2011-2022 走看看