在GUI应用中输出调试信息

在GUI应用中输出调试信息_第1张图片
DebugView

1. 写在前面的话

在调试程序的时候,最常用的办法就是打断点,看内存、堆栈等信息。但对一个GUI应用程序来讲,有时候我们不得不利用输出调试信息的方式来排查程序异常。比如调试鼠标hover事件、应用全屏等事件时,由于调试器本身也是GUI程序,当触发断点时,hover或全屏状态已经发生了改变,断点时的状态可能并不是我们期望的状态,这个时候就可以利用输出调试信息的方式来查看程序的状态。文本总结了在GUI应用程序中输出调试信息比较常用的三种方式。

2. 输出到调试器输出窗口中

将调试信息输出到调试器输出窗口(Output)是首选,也是用的最多的方法。对于一个GUI应用程序来讲,默认是没有控制台的,如果我们用标准输入输出函数,如printf, std::cout等,这些函数是不起作用的。但如果GUI应用程序在被调试状态下,调试器会将标准输出重定向到输出窗口,以下是在Visual Studio 2015中的输出:

在GUI应用中输出调试信息_第2张图片
Output-Debug

除了直接用标准输出函数输出调试信息外,VS调试器还支持条件式断点,即在触发某个条件的时候触发断点或输出信息到控制台,如:

在GUI应用中输出调试信息_第3张图片
Condition Breakpoint

当触发条件hWndButton为0时,会在输出窗口输出调试信息$FUNCTION: value x={x}, y={y},其中$FUNCTION是所在函数名,{x}{y}是栈上xy的变量值。

3. 输出到DebugView中

有时候我们的程序的运行环境中可能并没有可用的调试器,这个时候我们可以利用免费的sysinternals工具集中的DebugView来查看调试信息。使用DebugView的前提是,你需要使用OutputDebugString API输出调试信息。该工具不仅可以捕获用户态Win32应用程序的调试信息,还支持捕获内核态驱动程序的调试信息。我觉得该工具更好用的地方在于,它支持过滤规则的设置,并且支持一些通配符,可以很方便地过滤出我们想要查看的信息,如:

在GUI应用中输出调试信息_第4张图片
DebugView Filter

在GUI应用中输出调试信息_第5张图片
DebugView

4. 输出到标准控制台中

最后一种稍微麻烦点,需要写几行代码,先说一下其工作原理。我们在写Win32控制台程序的时候,有一个标准输入输出的命令行窗口供用户跟程序交互,虽然控制台应用程序在交互上不够友好,但标准输出的信息却可以在窗口中直观查看。而对于Win32 GUI应用,默认是没有那个控制台的。其实Win32控制台程序和Win32 GUI程序并没有严格的界线,我们可以在Win32控制台程序中展示窗口,也可以在Win32 GUI程序中展示控制台。

Windows提供了一个API叫 AllocConsole可以创建一个控制台,但即使控制台创建成功后,当你调用函数printf或std::cout时,发现仍然不能输出到控制台中,因为Win32 GUI程序默认将标准输入(stdin)、标准输出(stdout),标准错误输出(stderr)都设置为了0, 我们需要重新将其关联到创建的控制台上,其实现如下:

#include 
#include 
#include 

int WINAPI wWinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPWSTR lpCmdLine,
    int nCmdShow)
{
    ::AllocConsole();
    FILE* pfStdOut = nullptr;
    FILE* pfStdIn = nullptr;
    freopen_s(pfStdOut, "CONOUT$", "w", stdout);
    freopen_s(pfStdIn, "CONIN$", "r", stdin);
    fprintf(stdout, "fprintf::test\n");
    printf("printf::test\n");
    std::cout << "cout::test" << std::endl;
    ::FreeConsole();
    return 0;
}

运行结果如下:


在GUI应用中输出调试信息_第6张图片
image.png
  1. 更多参考
    [1]. http://dslweb.nwnexus.com/~ast/dload/guicon.htm
    [2]. https://stackoverflow.com/questions/32185512/output-to-console-from-a-win32-gui-application-on-windows-10#
    [3]. https://www.codeproject.com/Articles/15836/Writing-to-and-read-from-the-console-From-a-GUI-ap
    [4]. https://docs.microsoft.com/zh-cn/sysinternals/

你可能感兴趣的:(在GUI应用中输出调试信息)