将可变模板参数转发到类似printf的函数
Forwarding variadic template parameter to printf-like function
我有以下日志函数:
template<typename... Arguments>
void Log(const char* file, const int line, int level, const char* fmt, Arguments... args)
{
std::string formattedFile;
if (file)
{
boost::filesystem::path p(file);
formattedFile = p.filename().string();
}
std::string message{boost::str(boost::format("%1%:%2% [%3%] - %s") % formattedFile % line % m_uxid % fmt)};
__android_log_print(level, m_tag.c_str(), message.c_str(), args...);
}
该应用程序使用NDK在Android上运行,因此这是该平台的日志记录系统。问题是__android_log_print()
无法使用进行编译
error: format not a string literal and no format arguments [-Werror=format-security]
__android_log_print(level, m_tag.c_str(), message.c_str(), std::forward<Arguments>(args)...);
^
我不知道这意味着什么。我是否没有正确使用可变模板参数?
printf
中不受信任的输入可能是一个安全问题。使用字符串文字强制格式是提高安全性的一种方法
将警告转换为错误将导致生成失败,因此您必须处理警告。
GCC的警告选项是这样说的
-Werror
:
将所有警告转化为错误。
-Wformat-security
:
警告使用表示可能存在安全问题的格式函数
目前,这会警告对printf和scanf函数的调用,其中格式字符串不是字符串文字并且没有格式参数
如果格式字符串来自不受信任的输入并且包含%n
,则这可能是一个安全漏洞。
通常建议在函数中创建一个std::string
,并将其与%s
格式的字符串文字一起传递给日志记录函数
__android_log_print(level, m_tag.c_str(), "%s", message.c_str());
其中,消息是通过处理args...
构建的,通常使用类似boost::format
或std::stringstream
的东西。
如果你想使用你提供的fmt
字符串和可变参数,你可以使用一个自定义的printf
风格的函数来解析这些参数,这个函数会产生一个std::string
std::string va_string_printf(const char* format, va_list ap)
{
char stack_buf[256];
char* buf = stack_buf;
int buf_size = sizeof(stack_buf);
std::string out_str;
while(true)
{
va_list ap1;
va_copy(ap1, ap);
int min_buf_size = vsnprintf(buf, buf_size, format, ap1) + 1;
va_end(ap1);
if (min_buf_size > buf_size)
{
if (buf != stack_buf) // allocate a bigger buffer
delete[] buf;
buf = new char[min_buf_size];
buf_size = min_buf_size;
continue;
}
out_str = buf;
break;
}
if (buf != stack_buf)
delete[] buf;
return out_str;
}
std::string string_printf(const char* format, ...)
{
va_list ap;
va_start(ap, format);
std::string str = va_string_printf(format, ap);
va_end(ap);
return str;
}
相关文章:
- 如何在类成员函数中获得类似printf中的编译警告
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类
- C++ 如果 Printf 位于函数中,则返回是不同的
- 点在printf函数中是什么意思
- 为什么 printf 函数在以下代码中显示所需的输出
- 在VS2013与VS2017的printf函数中使用宏
- 为什么printf()函数打破了C中的指针adress
- 我可以从函数返回 printf 语句吗?C++
- std::locale::global是否影响printf()函数
- 显示类变量.在 printf 函数中使用字符串作为参数
- 当使用另一个函数封装 printf 和 vfprintf 时,这种差异的原因是什么?
- 为什么printf函数家族关心区域设置
- 从自定义 printf 函数返回一个常量字符*
- printf 函数C++参数化前导零
- printf函数是如何工作的
- printf函数参数之间的序列点;转换之间的顺序点是否重要
- 自己的printf函数不起作用
- 使用printf函数
- 如何在arm可执行文件中获取printf函数的地址
- HLSL中的printf函数做什么?