即使输出被截断,vsnprintf() 也会使用所有 va_list 参数吗?

问题描述 投票:0回答:1

我正在制作一个具有类似 printf 功能的日志函数:

log(LOG_LEVEL lvl, const char* fmt, ...)

LOG_LEVEL
只是一个枚举(0 很重要,更高则不太重要)。

如果

lvl
高于另一个变量(例如,
current_log_level
),我想尽可能少地做并快速返回。但是,我担心不使用
fmt
之后的参数会破坏堆栈,并且如果可能的话,我想避免编写自己的“检查 fmt 并根据需要调用 va_arg()”,以避免与
printf 可能出现的差异
格式,所以我考虑使用
vsnprintf
并让输出字符串的长度尽可能小。

根据文档,对于

vsnprintf
,如果长度设置为0,输出字符串可以为空,但我不确定这是否会使用所有剩余的参数,或者它是否只是停止处理并返回。

想象一下以下内容(我正在使用 C++17,但我认为这也适用于优秀的旧 C):

enum class LOG_LEVEL : unsigned int { ERROR, WARNING };

LOG_LEVEL current_log_level = LOG_LEVEL::WARNING;

void log(LOG_LEVEL lvl, const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    if (static_cast<unsigned int>(lvl) <= static_cast<unsigned int>(current_log_level))
    {
        /* lock a mutex, write to a file and/or whatever */
    }
    else
    {
        vsnprintf(nullptr, 0, fmt, args);
    }

    va_end(args);
}

我觉得

vsnprintf
(和其他 v*printf 函数)应该使用所有参数,即使它被截断,(如果没有,这在许多程序中将是一个很好的安全问题),但在 man 中没有提到页面,我找不到任何信息。也许我的搜索能力不够好。或者也许有更好、更快和/或更简单的方法来做到这一点?

c++ c variadic-functions
1个回答
0
投票

即使输出被截断,vsnprintf() 也会使用所有 va_list 参数吗?

是一个实现细节。结果必须被截断。 如何实现未指定 - 潜在地,

vsnprintf
源代码可以检查输出是否更长,然后停止处理。

我觉得 vsnprintf (和其他 v*printf 函数)应该使用所有参数,即使它截断

我觉得这是一种不合理的感觉。参数存在于堆栈中,它们就在那里。如果它们没有被访问,就没有被访问,什么也不会发生。

当你什么都不想做的时候,就什么也不做。提前返回看起来像是这里使用的一种风格。

void log(LOG_LEVEL lvl, const char* fmt, ...)  {
    if (static_cast<unsigned int>(lvl) > static_cast<unsigned int>(current_log_level)) {
          return;
    }
    va_list args;
    va_start(args, fmt);
    /* lock a mutex, write to a file and/or whatever */
    va_end(args);
}
© www.soinside.com 2019 - 2024. All rights reserved.