C++11 如何检测snprintf故障?

C++11 如何检测snprintf故障?,c++11,printf,C++11,Printf,我正在使用snprintf使用用户定义的格式(也称为字符串)格式化字符串。代码如下所示: void DataPoint::valueReceived( QVariant value ) { // Get the formating QVariant, which is only considered valid if it's string QVariant format = this->property("format"); if( format.isValid(

我正在使用
snprintf
使用用户定义的格式(也称为字符串)格式化字符串。代码如下所示:

void DataPoint::valueReceived( QVariant value ) {
    // Get the formating QVariant, which is only considered valid if it's string
    QVariant format = this->property("format");
    if( format.isValid() && format.type()==QMetaType::QString && !format.isNull() ) {
        // Convert QString to std string
        const std::string formatStr = format.toString().toStdString();
        LOGMTRTTIINFO(pointName<<"="<<value.toString().toUtf8().constData()<<"=>"<<formatStr<<"["<<formatStr.length()<<'\n');
        // The attempt to catch exceptions caused by invalid formating string
        try {
            if( value.type() == QMetaType::QString ) {
                // Treat value as string (values are allways ASCII)
                const std::string array = value.toString().toStdString();
                const char* data = (char*)array.c_str();
                // Assume no more than 10 characters are added during formating.
                char* result = (char*)calloc(array.length()+10, sizeof(char));
                snprintf(result, array.length()+10, formatStr.c_str(), data);
                value = result;
            }
            // If not string, then it's a number.
            else {
                double data = value.toDouble();
                char* result = (char*)calloc(30, sizeof(char));
                // Even 15 characters is already longer than largest number you can make any sense of
                snprintf(result, 30, formatStr.c_str(), data);
                LOGMTRTTIINFO(pointName<<"="<<data<<"=>"<<formatStr<<"["<<formatStr.length()<<"]=>"<<result<<'\n');
                value = result;
            }
        } catch(...) {
            LOGMTRTTIERR("Format error in "<<pointName<<'\n');
        }
    }
    ui->value->setText(value.toString());
}
void DataPoint::valueReceived(QVariant值){
//获取格式化QVariant,它只有在为字符串时才被视为有效
QVariant format=此->属性(“格式”);
if(format.isValid()&&format.type()==QMetaType::QString&&!format.isNull()){
//将QString转换为标准字符串
const std::string formatStr=format.toString().tostString();

LOGMTRTTIINFO(pointName
snprintf
失败时会发生什么?


snprintf
失败时,POSIX要求设置错误号:

如果遇到输出错误,这些函数应返回负值并设置errno以指示错误


您还可以找到一些有关如何处理
snprintf
故障的相关信息。

您询问是否有可能在运行时检测到格式/参数不匹配,对吗?那么简短且唯一的答案是

扩展“否”是因为变量参数函数(使用省略号的函数)没有类型安全性。编译器会将某些类型的参数转换为其他类型(例如,
char
short
将转换为
int
float
将转换为
double
),如果使用文本字符串作为格式,某些编译器将能够解析字符串并检查传递的参数


但是,由于您传递的变量字符串可能在运行时更改,因此编译器不可能进行任何类型的编译时检查,并且函数必须相信传递的格式字符串对传递的参数使用了正确的格式。如果不是,则您有未定义的行为。

首先,您知道
snprintf
是一个C函数,因此不会引发任何异常。其次,您应该尝试在调试器中逐步检查代码,以查看实际的格式字符串和试图作为参数传递的实际值。@JoachimPileborg我传递了一个
双精度
%s
。我不需要调试器来查看它,我有日志消息好了。我不明白你为什么有任何疑问。你知道在
*printf()
*scanf()
中使用用户提供的格式字符串是潜在的安全漏洞吗?等等,你是在告诉我们你使用该格式“打印”吗一个字符串,然后你传递一个
双精度
?你希望它如何工作?它已经被导入了(某种程度上)进入C++标准库,但它仍然是调用的C函数。变量参数函数的问题,不管它们是C还是C++,都是没有任何类型的安全性。可以传递任何参数作为参数,函数仍然使用(和信任)。用于分析参数的格式字符串。一个好的编译器可以使用格式字符串(如果它是字符串文字而不是运行时变量)来验证传递的参数,但是在运行时无法验证参数。好的,非常感谢。我接受了另一个答案,因为它直接解决了标题中的问题(这对谷歌搜索很重要)。但也谢谢你的帮助。