65.9K
CodeProject 正在变化。 阅读更多。
Home

使用输出流进行调试

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (14投票s)

2001年4月11日

公共领域

2分钟阅读

viewsIcon

243115

如何创建写入调试终端的输出流

背景

调试程序的方法有很多种(是的,我知道 - 从一开始就写出正确的代码),但无论你喜欢什么工具,使用 printf 方法通常非常方便。好吧,既然你是一位现代 C++ 程序员,你可能并不真正想要 printf,而是想要使用一个输出流,比如 cerr

但只有一个问题,你正在编写 Windows 应用程序,所以没有标准的错误输出可以写入。实际上并非如此,确实有,而且你可能已经多次使用过它。当你使用 TRACE 宏之一时,结果会出现在 Visual Studio 的调试窗格中。MFC 会尽力在发布版本中关闭所有这些调试输出,但保留它通常非常方便。

当然,你不会在发布版本中从 Visual Studio 看到任何输出,但有其他程序可以捕获此输出。一个不错的选择是 DebugView,来自 www.sysinternals.com。顺便说一下,如果你启动这个程序,你可能会看到来自 Internet Explorer 的大约一百万条消息。你看,即使是微软也在练习发布版本调试!

问题

那么,如何将标准输出流定向到调试终端?一般来说,正确的答案是继承自 streambuf 并将新类连接到正常的 ostream。这样,所有流插入器和操纵符都能按预期工作。在这种情况下,我们可以通过继承自 stringbuf 来节省一些工作。所以,无需赘述,以下是如何操作。

代码

首先,我们包含所需的头文件。

#include <Windows.h>
#include <ostream>
#include <sstream>
#include <string>

现在开始实际工作:由于我们正在使用 stringbuf,我们只需要重写 sync 函数。

sync 方法实际上是将 put 区域中的文本传输到 streambuf 使用的任何输出目标,在本例中通过调用 API 函数 OutputDebugString

template <class CharT, class TraitsT = std::char_traits<CharT> >
class basic_debugbuf : 
    public std::basic_stringbuf<CharT, TraitsT>
{
public:

    virtual ~basic_debugbuf()
    {
        sync();
    }

protected:

    int sync()
    {
        output_debug_string(str().c_str());
        str(std::basic_string<CharT>());    // Clear the string buffer

        return 0;
    }

    void output_debug_string(const CharT *text) {}
};

接下来,我专门化输出例程,使其根据需要调用 Ansi 或 Unicode API。

template<>
void basic_debugbuf<char>::output_debug_string(const char *text)
{
    ::OutputDebugStringA(text);
}

template<>
void basic_debugbuf<wchar_t>::output_debug_string(const wchar_t *text)
{
    ::OutputDebugStringW(text);
}

这基本上就是你所需要的,但为了方便起见,我还提供了一个从 basic_ostream 派生的类,该类将输出流连接到刚刚创建的 basic_debugbuf

为了像 cout 一样工作,你应该创建一个类型为 dostreamwdostream 的全局对象,并使用它进行输出。

template<class CharT, class TraitsT = std::char_traits<CharT> >
class basic_dostream : 
    public std::basic_ostream<CharT, TraitsT>
{
public:

    basic_dostream() : std::basic_ostream<CharT, TraitsT>
                (new basic_debugbuf<CharT, TraitsT>()) {}
    ~basic_dostream() 
    {
        delete rdbuf(); 
    }
};

typedef basic_dostream<char>    dostream;
typedef basic_dostream<wchar_t> wdostream;

历史

  • 2001年4月18日 - 原始版本
  • 2001年11月23日 - 更新为使用 Jim Barry 建议的 stringbuf
    同时修复了剩余的 HTML 标记错误,这些错误导致代码无法编译
© . All rights reserved.