分类 调试 下的文章

书接上文《C++ EH Exception(0xe06d7363)----抛出过程》,下面我们讲下,VC++是如何catch到异常且处理的。

我们知道,在VC++里,C++异常实现的底层机制还是SEH,所以,我们将程序跑起来观察

上图红框框起来的部分就是编译器安装了异常处理链,且将其设置位最后一个节点,也就如下结构

struct VC_EXCEPTION_REGISTRATION
{
     VC_EXCEPTION_REGISTRATION* prev;    //前一个结构体的指针
     FARPROC                    handler; //永远指向_exception_handler4回调函数
     scopetable_entry*          scopetable;//指向scpoetable数组的指针
     int                        _index; //有的书上也叫tryLevel。scopetable项的当前项
     DWORD                      _ebp;   //当前ebp值,用于访问各成员
}

有时,可能需要调试由另一个进程启动的应用程序的启动代码。 这样的示例包括服务和自定义设置操作。 在这些情况下,可以让调试器在应用程序启动时启动并自动附加。

设置应用程序以自动启动调试器

  1. 启动注册表编辑器 (regedit)。

  2. 在“注册表编辑器”中打开 HKEY_LOCAL_MACHINE 文件夹。

  3. 定位到 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\currentversion\image file execution options。

  4. 在“Image File Execution Options”文件夹中,找到要调试的应用程序的名称,如 myapp.exe。 如果无法找到要调试的应用程序:


    1. 右击“Image File Execution Options”文件夹,在快捷菜单上单击“新建项”。

    2. 右击新项,然后在快捷菜单上单击“重命名”。

    3. 将项名编辑成您的应用程序的名称;在本示例中为 myapp.exe。

  5. 右击 myapp.exe 文件夹,在快捷菜单上单击“新建字符串值”。

  6. 右击新的字符串值,然后在快捷菜单上单击“重命名”。

  7. 将名称更改为 debugger。

  8. 右击新的字符串值,并在快捷菜单上单击“修改”。

    即显示“编辑字符串”对话框。

  9. 在“数值数据”框中,键入 vsjitdebugger.exe。

  10. 单击“确定”。

  11. 在“注册表”菜单中,单击“退出”。

  12. 包含 vsjitdebugger.exe 的目录必须位于系统路径中。 要将其添加到系统路径,请执行下列步骤:


    1. 以经典视图打开“控制面板”,并双击“系统”。

    2. 单击“高级系统设置”。

    3. 在“系统属性”中,单击“高级”选项卡。

    4. 在“高级”选项卡上,单击“环境变量”。

    5. 在“环境变量”对话框中的“系统变量”下,选择“路径”,然后单击“编辑”按钮。

    6. 在“编辑系统变量”对话框中,将该目录添加到“变量值”框中。 使用分号将它与列表中的其他项隔开。

    7. 单击“确定”关闭“编辑系统变量”对话框。

    8. 单击“确定”关闭“环境变量”对话框。

    9. 单击“确定”关闭“系统属性”对话框。


    现在,使用任意方法启动该应用程序。 Visual Studio 将启动并加载该应用程序。

在运行于 Visual Studio 之外的应用程序中发生异常或崩溃时,实时调试会自动启用 Visual Studio。 这样,您便可以在 Visual Studio 没有运行时测试应用程序,并在出现问题时利用 Visual Studio 开始调试。

实时调试不适用于在可视化工具等本机应用程序中承载的托管代码。 如果您在 Windows Server 2003 或 Windows 2000 SP3(或更高版本)中安装 .NET Framework,那么,只有在计算机重新启动后,才可以对在终端服务会话中通过受限用户帐户运行的进程使用实时调试。

使用实时调试

默认情况下,安装 Visual Studio 时会启用实时调试。启用实时调试之后,您可以在 Visual Studio 之外调试应用程序。 如果发生崩溃或异常,将会出现一个对话框,其中显示一条与下面类似的消息:在 terrarium.exe[3384] 中发生未经处理的异常(“System.TypeInitializationException”)

如果出现此对话框,您可以通过以下步骤开始调试。

发生错误时开始实时调试

  1. 在“实时调试”对话框中,在“可能的调试器”列表中,单击“Visual Studio  新实例”或单击已在运行的 Visual Studio 2010。

  2. 若要在以后发生崩溃时都自动使用 Visual Studio,请单击“将当前选定的调试器设置为默认调试器”。

  3. 如果要选择能够调试的代码类型,请单击“手动选择调试引擎”。 如果没有选择此选项,Visual Studio 将根据程序中的代码类型自动选择合适的调试引擎。

  4. 单击“确定”。

  5. 如果在您的应用程序中,某个程序集包含不受信任的代码,则会出现一个对话框以及一条安全警告。 此对话框使可以决定是否继续调试。 在继续调试之前,请决定您是否信任相应代码。 代码是您自己编写的吗? 您是否信任代码编写者? 如果该应用程序正在远程计算机上运行,您是否认识进程的名称? 即便该应用程序在本地运行,也不一定表示它是可信的应用程序。 例如,在 Internet Explorer 中可能会有恶意 ActiveX 控件运行。 请考虑此类恶意代码在您的计算机中运行的可能性。 如果您确信待调试代码值得信任,请单击“调试”。 否则,请单击“不调试”。

启用或禁用实时调试

您可以在“选项”对话框中启用或禁用实时调试。

启用或禁用实时调试

  1. 在“工具”菜单上,单击“选项”。

  2. 在“选项”对话框中选择“调试”文件夹。

  3. 在“调试”文件夹中选择“实时”页。

  4. 在“启用这些代码类型的实时调试”框中,选中或清除相关的程序类型:“托管”、“本机”或“脚本”。

    要在启用实时调试后禁用它,必须使用管理员特权运行。 启用实时调试会设置一个注册表项,需要管理员特权才可以更改该项。

  5. 单击“确定”。

默认情况下,Windows 窗体应用程序有一个顶级的异常处理程序,该处理程序允许程序在能够恢复时继续运行。 因此,若要启用 Windows 窗体应用程序的实时调试,还必须执行下列步骤。

为 Windows 窗体启用实时调试

  1. 在 machine.config 或应用程序.exe.config 文件的 system.windows.form 节中,将 jitDebugging 值设置为 true。

  • <configuration>
        <system.windows.forms jitDebugging="true" />
    </configuration>
    
  • 在 C++ Windows 窗体应用程序中,还必须在 .config 文件或您的代码中设置 DebuggableAttribute。 如果在编译时使用 /Zi 而没有使用 /Og,则编译器会替您设置此特性。 然而,如果您想要调试非优化发布版本,则必须自行设置此项。 为此,您可以在应用程序的 AssemblyInfo.cpp 文件中添加下面一行:

  1. [assembly:System::Diagnostics::DebuggableAttribute(true, true)]; 

即便在您的计算机中不再安装有 Visual Studio,仍可启用实时调试。 如果没有安装 Visual Studio,则不能在 Visual Studio“选项”对话框中禁用实时调试。 对于这种情况,您可以通过编辑 Windows 注册表来禁用实时调试。

通过编辑注册表禁用实时调试

  1. 在“开始”菜单中,单击“运行”。

  2. 在“运行”对话框中,键入 regedit,然后单击“确定”。

  3. 在“注册表编辑器”窗口中,找到并删除下列注册表项:


    • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger

    • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DbgManagedDebugger

  4. 如果您的计算机运行的是 64 位操作系统,还请删除下列注册表项:


    • HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger

    • HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\DbgManagedDebugger

  5. 注意不要意外删除或更改任何其他注册表项。

  6. 关闭“注册表编辑器”窗口。

实时调试错误

您可能会遇到与实时调试相关联的下列错误消息。

  • <程序> 中发生未处理的 win32 异常。对此异常的实时调试失败,错误为: 登录用户没有调试崩溃应用程序的权限。

    此信息指出:由于您没有正确的访问权限,实时调试失败。

  • 无法附加到崩溃进程。 指定的程序不是 Windows 或 MS-DOS 程序。

    当您尝试附加到 Windows 2000 下作为另一个用户运行的进程时会发生该错误。

    若要解决此问题,请启动 Visual Studio,从“调试”菜单打开“附加到进程”对话框,然后在“可用进程”列表中找到您要调试的进程。 如果您不知道进程名称,请查看“Visual Studio 实时调试器”对话框并记下进程 ID。 在“可用进程”列表中选择该进程并单击“附加”。 在“Visual Studio 实时调试器”对话框中单击“否”以关闭该对话框。

  • 未能启动调试器,因为没有用户登录。

    在没有用户登录到控制台的计算机中,如果实时调试尝试启动 Visual Studio,则会发生此错误。 因为没有用户登录,所以没有用户会话来显示“实时调试”对话框。

    要解决此问题,请登录到计算机。

  • 类没有注册。

    此错误指出:调试器尝试创建一个可能是因为安装问题而没有注册的 COM 类。

    若要解决此问题,请使用安装盘重新安装或修复 Visual Studio 安装。

e, ea, eb, ed, eD, ef, ep, eq, eu, ew, eza (Enter Values)

e*命令将您指定的值输入内存。不要将此命令与~e(Thread-Specific Command)限定符混淆。

e{b|d|D|f|p|q|w} Address [Values] 
e{a|u|za|zu} Address "String" 
e Address [Values]