【问题标题】:How to determine buffer size for vswprintf under Linux gcc如何在 Linux gcc 下确定 vswprintf 的缓冲区大小
【发布时间】:2012-10-19 05:37:42
【问题描述】:

我需要为格式化函数 vswprintf() 分配足够的缓冲区。当使用 ANSI 字符串做同样的事情时,我使用的是:

vsnprintf( NULL, NULL, pszFormat, args );

它返回我所需的缓冲区大小。但是这个函数的unicode版本似乎没有这个功能。当我执行时:

vswprintf( NULL, NULL, pszFormat, args );

结果值始终为 -1。

我发现的唯一解决方案是使用大型静态缓冲区来计算所需的大小。但我不喜欢这个解决方案:

static const int nBuffSize = 1024;
static XCHAR evalBuff[nBuffSize];
int nSize = vswprintf( evalBuff, nBuffSize, pszFormat, args );
if ( nSize != -1 )
{
 return nSize;
}
else
{
 throw XXX;
}

有什么方法可以测量 unicode 字符串所需的缓冲区大小吗?

问候 卢德克

【问题讨论】:

    标签: c++ gcc unicode


    【解决方案1】:

    打开一个虚拟文件到 /dev/null(或 Windows 下的 NUL)并打印到该文件以检索大小效果非常好(它比打印到字符串更快):

    #if !defined(_MSC_VER)
    printf_dummy_file = fopen("/dev/null", "wb");
    #其他
    printf_dummy_file = fopen("NUL", "wb");
    #endif

    ...

    n = vfprintf(printf_dummy_file, format, args);

    “fopen”部分应该执行一次(您可以使用静态变量,或者如果您使用 C++,则可以使用全局变量的构造函数)。

    【讨论】:

    • vfwprintf 而不是 vfprintf,但无论如何 +1。并记得使用 va_list 的副本。
    • 感谢您的提示。该解决方案的唯一缺点是比原始函数 vswprintf 慢 5 倍。所以我会在 *nix 系统上使用这个功能,但在 Win 系统上使用原始功能。谢谢
    【解决方案2】:

    有点重量级,但如果没有人想出更好的方法,你可以成倍增长缓冲区,直到它足够大:

    std::vector<wchar_t> vec(512);
    int nSize;
    do {
        vec.resize(vec.size()*2);
        va_list args2;
        va_copy args2, args;
        nSize = vswprintf(&vec[0], vec.size(), format, args2);
        va_end args2
    } while(nSize < 0);
    // now I have the length, and the formatted string to copy if required.
    

    由于您使用的是 POSIX,您会认为会为缓冲区空间不足定义一个 errno,并且应该在 while 条件下检查此 errno,以便其他错误不会导致资源-饥饿的循环。但是http://opengroup.org/onlinepubs/007908775/xsh/fwprintf.html 没有定义这样的 errno,所以我想你必须测试你在实现中实际得到的 errno(如果有的话)。

    另一种选择是去掉格式字符串,改为写入wostringstream。但是,如果您的格式字符串需要在编译时配置后,这并没有多大用处。

    【讨论】:

    • 感谢您提供此提示,但它比 John Rusta 建议的解决方案更耗时,因此我决定采用他的方式。谢谢
    【解决方案3】:

    这将获得缓冲区大小:

    vswprintf(nullptr, -1, pszFormat, args);

    【讨论】:

    • @Programmdude:它将为你们所有人返回 -1,这恰好在您的代码(或 using std::vswprintf)的某处有一个 using namespace std;。对于其他所有人,它将返回所需的缓冲区大小(或编译器错误)。
    • @IInspectable 您的评论是错误的,C++ 将 vswprintf 的 C 规范委托给 C 规范,但未指定任何行为更改;并且 C 规范说 vswprintf 使得将空指针作为第一个参数传递是未定义的行为
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 2018-10-14
    • 1970-01-01
    相关资源
    最近更新 更多