C++ 将零参数包传递给printf
我创建了一个具有可变模板方法的类。此方法调用C++ 将零参数包传递给printf,c++,gcc,variadic,C++,Gcc,Variadic,我创建了一个具有可变模板方法的类。此方法调用printf函数。将零参数传递给该方法时,gcc会发出编译警告,警告如下: 警告:格式不是字符串文字,也没有格式参数[-Wformat security] 一个简化的类示例是: class printer{ std::map<int,std::string> str; public: printer(){ str[0] = "null\n"; str[1] = "%4d\n"; str
printf
函数。将零参数传递给该方法时,gcc会发出编译警告,警告如下:
警告:格式不是字符串文字,也没有格式参数[-Wformat security]
一个简化的类示例是:
class printer{
std::map<int,std::string> str;
public:
printer(){
str[0] = "null\n";
str[1] = "%4d\n";
str[2] = "%4d %4d\n";
str[3] = "%4d %4d\n%4d\n";
}
template<typename ...Args>
void print(Args... args){
printf(str[sizeof...(args)].c_str(),args...);
}
};
一切编译都很顺利,但使用
printer p;
p.print(23);
p.print(345,23);
printer p;
p.print();
我得到了警告
main.cpp: In instantiation of ‘void printer::print(Args ...) [with Args = {}]’:
main.cpp:23:11: required from here
main.cpp:17:50: warning: format not a string literal and no format arguments [-Wformat-security]
printf(str[sizeof...(args)].c_str(),args...);
当然,如果我打电话的话
printf("null\n");
没有出现警告
有人能解释为什么会这样吗
我可以在不禁用
-Wformat security
标志的情况下删除警告吗?这是一个预期的警告,如果我们查看文档中的说明:
-格式安全
如果指定了-Wformat,还将警告使用表示可能存在安全问题的格式函数。目前,这会警告调用printf和scanf函数时,格式字符串不是字符串文字,并且没有格式参数,如printf(foo)。如果格式字符串来自不受信任的输入并包含“%n”,则这可能是一个安全漏洞。(这是-Wformat nonliteral警告的一个子集,但将来可能会在-Wformat nonliteral中未包含的-Wformat security中添加警告。)
-Wformat=2
由于c_str()
的结果不是字符串文字,因此不传递任何参数就是这种情况
本案:
printf("null\n");
不发出警告,因为“null\n”
是一个字符串文字,不可能从用户输入
我们可以从中看出为什么这是一个潜在的安全问题
如果您不想使用所有的-Wformat security
,则必须打开特定的开关:
-Wformat包含在-Wall中。为了更好地控制格式检查的某些方面,可以使用选项-Wformat-y2k、-Wno-format-extra-args、-Wno-format-zero-length、-Wformat-nonliteral、-Wformat-security和-Wformat=2,但不包括在-Wall中
虽然如果以后-Wformat security
添加了更多选项,这是一个糟糕的选项,但是您需要不断地更新
AndyG提到的另一种选择是过载:
void print(){
std::printf("null\n");
}
我问了一个几乎相同的问题。不要将此标记为重复,因为我不确定您是否可以在我建议的解决方案中使用类似的宏。如果它工作,请把它复制。现在C++有<代码> Prtff < /代码>吗?您正在调用C
printf
…@AnttiHaapala有std::printf
…)将OP的print
函数重载为一个不带参数的函数(一个“不做任何事情”的函数)是不是一个好主意?我不明白的是:为什么无文字警告只在零参数情况下出现,而在其他情况下不出现?@ctheo请看my的例子,了解为什么无参数情况是一个问题。@AndyG是的,我想补充一下,不得不走开。谢谢@ShafikYaghmour。因此,可以通过-Wformat nonliteral
选项来避免警告。现在的挑战是如何真正保护软件免受格式化攻击。也许我稍后会发布另一个问题。