jsoncpp v0.5中的一个bug

简介:

本文目的

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

 

一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
  * 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的源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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函数的实现,源代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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]

声明:如有转载本博文章,请注明出处。您的支持是我的动力!文章部分内容来自互联网,本人不负任何法律责任。
本文转自bourneli博客园博客,原文链接:http://www.cnblogs.com/bourneli/archive/2011/12/28/2304618.html ,如需转载请自行联系原作者
相关文章
|
11月前
|
编译器 Linux 数据库
[✔️]FFMpeg编译32位踩坑指南
[✔️]FFMpeg编译32位踩坑指南
713 0
|
12月前
|
Java API 开发工具
Magisk 最新版本 V24.1 源码编译踩坑集锦
Magisk 最新版本 V24.1 源码编译踩坑集锦
410 0
SVN遗漏so文件的解决办法
SVN遗漏so文件的解决办法
62 0
SVN遗漏so文件的解决办法
又编译了一次doubango整个项目
又编译了一次doubango整个项目
38 0
|
Linux
LINUX编译时缺少头文件,查找依赖库的终极解决办法
LINUX编译时缺少头文件,查找依赖库的终极解决办法
318 0
|
Ubuntu Windows
Jpeglib开发笔记(二):JpegLib编译(ubutnu)和Demo
Jpeglib开发笔记(二):JpegLib编译(ubutnu)和Demo
Jpeglib开发笔记(二):JpegLib编译(ubutnu)和Demo
|
C++ 计算机视觉 Windows
Jpeglib开发笔记(一):JpegLib库介绍、windows编译和Demo
Jpeglib开发笔记(一):JpegLib库介绍、windows编译和Demo
Jpeglib开发笔记(一):JpegLib库介绍、windows编译和Demo
好奇怪:编译好的doubango,又不能编译通过了
好奇怪:编译好的doubango,又不能编译通过了
105 0
|
JSON C++ 数据格式
VS2008中使用JSONCPP方法小结
Introduction JSON (JavaScript Object Notation) is a lightweight data-interchange format. It can represent integer, real number, string, an ordered seq...
908 0