zoukankan      html  css  js  c++  java
  • jsoncpp v0.5中的一个bug

    本文目的

    今天在使用jsoncpp 0.5的时候很偶然的发现了一个bug,由于jsoncpp在业界被广泛使用,所以有必要将这个bug指出。

    一个例子

    /*
     * bug_demo.cpp
     *
     *  Created on: 2011-11-22
     *      Author: bourneli
     */
    #include "json/json.h"
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
        Json::Value oRootVal;
    
        Json::Reader oJsonReader;
        oJsonReader.parse("{\"aInt\" : 3}", oRootVal);
    
        Json::Value oInt = oRootVal["aInt"];
        cout << "aInt : " << oInt.asInt() << endl;
        if (oInt.isConvertibleTo(Json::stringValue))
        {
            cout << "aInt as string : " << oInt.asString() << endl;
        }
        else
        {
            cout << "aInt cannot convert to a string" << endl;
        }
        return 0;
    }

    根据上面的代码,如果使用过jsoncpp,应该可以预测输出,如下:

    aInt : 3

    aInt as string : 3

    但是,实际上却是:

    clip_image002

    抛异常了 囧~~~

    原因分析

    Json::Value::isConvertibleTo函数,从字面意思上看,就是判断当前value是否可以转成目标类型,我们看看Json::Value::isConvertibleTo的源代码:

    bool 
    Value::isConvertibleTo( ValueType other ) const
    {
       switch ( type_ )
       {
       case nullValue:
          return true;
       case intValue:
          return ( other == nullValue  &&  value_.int_ == 0 )
                 || other == intValue
                 || ( other == uintValue  && value_.int_ >= 0 )
                 || other == realValue
                 || other == stringValue
                 || other == booleanValue;
       case uintValue:
          return ( other == nullValue  &&  value_.uint_ == 0 )
                 || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
                 || other == uintValue
                 || other == realValue
                 || other == stringValue
                 || other == booleanValue;
       case realValue:
          return ( other == nullValue  &&  value_.real_ == 0.0 )
                 || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
                 || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
                 || other == realValue
                 || other == stringValue
                 || other == booleanValue;
       case booleanValue:
          return ( other == nullValue  &&  value_.bool_ == false )
                 || other == intValue
                 || other == uintValue
                 || other == realValue
                 || other == stringValue
                 || other == booleanValue;
       case stringValue:
          return other == stringValue
                 || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
       case arrayValue:
          return other == arrayValue
                 ||  ( other == nullValue  &&  value_.map_->size() == 0 );
       case objectValue:
          return other == objectValue
                 ||  ( other == nullValue  &&  value_.map_->size() == 0 );
       default:
          JSON_ASSERT_UNREACHABLE;
       }
       return false; // unreachable;
    }

    实现很简单,就是一系列的类型转换映射。上面的代码中第13行的地方就说明,int类型的Value是可以转化成string类型的Value。

    但是实际上,却抛出了异常,我们可以分析下Json::Value::AsString函数的实现,源代码如下:

    std::string 
    Value::asString() const
    {
       switch ( type_ )
       {
       case nullValue:
          return "";
       case stringValue:
          return value_.string_ ? value_.string_ : "";
       case booleanValue:
          return value_.bool_ ? "true" : "false";
       case intValue:
       case uintValue:
       case realValue:
       case arrayValue:
       case objectValue:
          JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
       default:
          JSON_ASSERT_UNREACHABLE;
       }
       return ""; // unreachable
    }

    实现也很简单,也是通过当前value的类型,判断是否可以转成string类型。第12行和第17行表明:转换映射和isConvertibleTo不一致。这就是导致bug的直接原因。

    总结

    此bug不是什么致命bug,并不能掩盖jsoncpp的跨平台,简单,轻量级等优点,使用的时候需要注意这里,否则会带来问题。所以,建议不要使用isConvertibleTo这个函数,而是通过手动判断当前数据类型,然后使用C++内置的类型转换,就不会出现该问题。

    相关资料

    下面的链接是jsoncpp在sourceforge官方网站上对该bug的描述

    https://sourceforge.net/tracker/index.php?func=detail&aid=3021877&group_id=144446&atid=758826

    没有注册的同学无法浏览,这里截个图:

    clip_image002[5]

  • 相关阅读:
    模块二
    lambda map() filter() zip()练习
    装饰器
    函数模块回顾
    连接不同数据OleDb(不完整)
    连接不同的数据库
    连接数据库ORACLE(不完整)
    多数据之间的连接操作ODBC(不完整)
    ora0131
    ORACLE linux 下 sqlplus命令
  • 原文地址:https://www.cnblogs.com/bourneli/p/2304618.html
Copyright © 2011-2022 走看看