如何检测snprintf失败?

时间:2015-12-07 12:52:31

标签: 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() && 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());
}

如你所见,我认为会有一些例外。但是没有,无效的格式化字符串会导致乱码。如果我尝试使用double格式%s

,这就是我得到的

image description

那么有没有办法检测到选择了无效格式化选项,例如将数字格式化为字符串,反之亦然?如果给出完全无效的格式化字符串怎么办?

2 个答案:

答案 0 :(得分:3)

你问是否可以在运行时检测格式/参数不匹配,对吧?然后,简短且唯一的答案是

要扩展“no”,因为Variable-argument函数(使用省略号...的函数)没有类型安全性。编译器会将某些类型的参数转换为其他参数(例如charshort将转换为intfloat将转换为double),以及如果你使用文字字符串作为格式,一些编译器将能够解析字符串并检查你传递的参数。

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

答案 1 :(得分:1)

snprintf失败后会发生什么?

snprintf失败时,POSIX要求设置errno:

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

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