有没有更好的方法将格式化的输出传递给OutputDebugString? [英] Is there a better way to pass formatted output to OutputDebugString?

查看:80
本文介绍了有没有更好的方法将格式化的输出传递给OutputDebugString?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,当我需要在Windows中调试输出时,我使用以下C代码段:

Typically, when I need to do debug output in Windows, I use the following C code segment:

#ifdef _DEBUG
#define DBGPRINT( kwszDebugFormatString, ... ) \
{ \
    wprintf_s( L"[%s:%d] ", __FUNCTIONW__, __LINE__ ); \
    wprintf_s( kwszDebugFormatString, __VA_ARGS__ ); \
}
#else
#define DBGPRINT( kwszDebugFormatString, ...) ;;
#endif

我想将其重新编码为使用不接受格式字符串的 OutputDebugString .我认为在堆栈上静态分配一个小数组(例如, WCHAR wszBuf [100] = {0}; )有点粗略,因为它可能比分配的内存消耗更多或更少的内存,或者截断输出或浪费内存.我编写了以下代码来解决所有这些问题,但是由于宏有点大,所以使我感到关注.

I'd like to recode this to use OutputDebugString which doesn't accept a format string. I consider statically allocating a small array on the stack (e.g., WCHAR wszBuf[100] = {0};) to be somewhat crude since it might consume significantly more or less memory than what is allocated and either truncate output or waste memory. I wrote the following code that addresses all of these concerns, but concerns me because the macro is a bit large.

#ifdef _DEBUG
#define DBGPRINT( kwszDebugFormatString, ... ) \
{ \
    INT iLineNumber = __LINE__; \
    FILE *fileNul = NULL; \
    INT cbFormatString = 0; \
    PWCHAR wszDebugString = NULL; \
    size_t st_Offset = 0; \
    \
    /* Determine the number of characters in the format string by writing to NUL. */\
    fopen_s( &fileNul, "nul", "w" ); \
    cbFormatString = fwprintf_s( fileNul, L"[%s:%d]", __FUNCTIONW__, iLineNumber ) * sizeof( WCHAR ); \
    cbFormatString += fwprintf_s( fileNul, kwszDebugFormatString, __VA_ARGS__ ) * sizeof( WCHAR ) + 2; \
    \
    /* Depending on the size of the format string, allocate space on the stack or the heap. */ \
    wszDebugString = (PWCHAR)_malloca( cbFormatString ); \
    \
    /* Populate the buffer with the contents of the format string. */ \
    StringCbPrintfW( wszDebugString, cbFormatString, L"[%s:%d]", __FUNCTIONW__, iLineNumber ); \
    StringCbLengthW( wszDebugString, cbFormatString, &st_Offset ); \
    StringCbPrintfW( &wszDebugString[st_Offset / sizeof(WCHAR)], cbFormatString - st_Offset, kwszDebugFormatString, __VA_ARGS__ ); \
    \
    OutputDebugStringW( wszDebugString ); \
    \
    _freea( wszDebugString ); \
    fclose( fileNul ); \
}
#else
#define DBGPRINT( kwszDebugFormatString, ... ) ;;
#endif

一些注意事项:

  • 我使用了_malloca()和_freea(),以便在输出应该足够小的情况下使用堆栈分配.
  • 我不知道有什么方法可以获取完全扩展格式字符串的正确大小.我能想到的最好的解决方案是将其转储到NUL并从那里计算出正确的大小.
  • 我使用了宏,因为我不相信使用函数时有一种简单的方法可以达到相同的结果.

我的问题很简单,由于某个原因或其他原因(尤其是由于规模或效率低下),此宏会被视为不良做法吗?如果是这样,我应该考虑哪些替代方案?

My question is, quite simply, would this macro be considered bad practice for one reason or another (particularly for size or inefficiency)? If so, what alternatives should I be considering?

万一其他人想知道,我使用了注释中的建议和选定的答案,并提出了以下代码.非常感谢所有发表评论或回答的人-如果您想共享一个聪明的方法,请随时添加更多内容!

In case anyone else is wondering, I used the suggestions from the comments and the selected answer and came up with the following code. Thank you so much to everyone who commented or answered - feel free to add more if you have a clever way of doing this that you want to share!

#ifdef _DEBUG
#define DBGPRINT(kwszDebugFormatString, ...) _DBGPRINT(__FUNCTIONW__, __LINE__, kwszDebugFormatString, __VA_ARGS__)

VOID _DBGPRINT( LPCWSTR kwszFunction, INT iLineNumber, LPCWSTR kwszDebugFormatString, ... ) \
{
    INT cbFormatString = 0;
    va_list args;
    PWCHAR wszDebugString = NULL;
    size_t st_Offset = 0;

    va_start( args, kwszDebugFormatString );

    cbFormatString = _scwprintf( L"[%s:%d] ", kwszFunction, iLineNumber ) * sizeof( WCHAR );
    cbFormatString += _vscwprintf( kwszDebugFormatString, args ) * sizeof( WCHAR ) + 2;

    /* Depending on the size of the format string, allocate space on the stack or the heap. */
    wszDebugString = (PWCHAR)_malloca( cbFormatString );

    /* Populate the buffer with the contents of the format string. */
    StringCbPrintfW( wszDebugString, cbFormatString, L"[%s:%d] ", kwszFunction, iLineNumber );
    StringCbLengthW( wszDebugString, cbFormatString, &st_Offset );
    StringCbVPrintfW( &wszDebugString[st_Offset / sizeof(WCHAR)], cbFormatString - st_Offset, kwszDebugFormatString, args );

    OutputDebugStringW( wszDebugString );

    _freea( wszDebugString );
    va_end( args );
}
#else
#define DBGPRINT( kwszDebugFormatString, ... ) ;;
#endif

推荐答案

如果您将所有代码放入普通的varargs函数中,然后在宏中调用该代码,则这样会更简单,并且更不会出错:

It would be much simpler and less error prone if you'd put all the code into a normal varargs function and then called that in your macro, similar to this:

void dbgprint(const wchar_t *func, int line, const wchar_t *fmt, ...) {
   // Fomat the string, maybe with vsprintf, log it, etc.
}

#define DBGPRINT(fmt, ...) dbgprint(__WFUNCTION__, __LINE__, fmt, __VA_ARGS__)

这篇关于有没有更好的方法将格式化的输出传递给OutputDebugString?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆