Skip to content

Commit 0f288ae

Browse files
committed
Use a Myers Singleton for null
Avoid some static initialization problems. From @marklakata See #488
1 parent e0f9aab commit 0f288ae

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

include/json/value.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ class JSON_API Value {
190190

191191
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
192192
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
193+
static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
194+
193195
/// Minimum signed integer value that can be stored in a Json::Value.
194196
static const LargestInt minLargestInt;
195197
/// Maximum signed integer value that can be stored in a Json::Value.

src/lib_json/json_value.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,22 @@ namespace Json {
3131
#else
3232
#define ALIGNAS(byte_alignment)
3333
#endif
34-
static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
35-
const unsigned char& kNullRef = kNull[0];
36-
const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
37-
const Value& Value::nullRef = null;
34+
//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
35+
//const unsigned char& kNullRef = kNull[0];
36+
//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
37+
//const Value& Value::nullRef = null;
38+
39+
// static
40+
Value const& Value::nullSingleton()
41+
{
42+
static Value const* nullStatic = new Value;
43+
return *nullStatic;
44+
}
45+
46+
// for backwards compatibility, we'll leave these global references around, but DO NOT
47+
// use them in JSONCPP library code any more!
48+
Value const& Value::null = Value::nullSingleton();
49+
Value const& Value::nullRef = Value::nullSingleton();
3850

3951
const Int Value::minInt = Int(~(UInt(-1) / 2));
4052
const Int Value::maxInt = Int(UInt(-1) / 2);
@@ -972,7 +984,7 @@ Value& Value::operator[](ArrayIndex index) {
972984
if (it != value_.map_->end() && (*it).first == key)
973985
return (*it).second;
974986

975-
ObjectValues::value_type defaultValue(key, nullRef);
987+
ObjectValues::value_type defaultValue(key, nullSingleton());
976988
it = value_.map_->insert(it, defaultValue);
977989
return (*it).second;
978990
}
@@ -989,11 +1001,11 @@ const Value& Value::operator[](ArrayIndex index) const {
9891001
type_ == nullValue || type_ == arrayValue,
9901002
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
9911003
if (type_ == nullValue)
992-
return nullRef;
1004+
return nullSingleton();
9931005
CZString key(index);
9941006
ObjectValues::const_iterator it = value_.map_->find(key);
9951007
if (it == value_.map_->end())
996-
return nullRef;
1008+
return nullSingleton();
9971009
return (*it).second;
9981010
}
9991011

@@ -1027,7 +1039,7 @@ Value& Value::resolveReference(const char* key) {
10271039
if (it != value_.map_->end() && (*it).first == actualKey)
10281040
return (*it).second;
10291041

1030-
ObjectValues::value_type defaultValue(actualKey, nullRef);
1042+
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
10311043
it = value_.map_->insert(it, defaultValue);
10321044
Value& value = (*it).second;
10331045
return value;
@@ -1047,15 +1059,15 @@ Value& Value::resolveReference(char const* key, char const* cend)
10471059
if (it != value_.map_->end() && (*it).first == actualKey)
10481060
return (*it).second;
10491061

1050-
ObjectValues::value_type defaultValue(actualKey, nullRef);
1062+
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
10511063
it = value_.map_->insert(it, defaultValue);
10521064
Value& value = (*it).second;
10531065
return value;
10541066
}
10551067

10561068
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
10571069
const Value* value = &((*this)[index]);
1058-
return value == &nullRef ? defaultValue : *value;
1070+
return value == &nullSingleton() ? defaultValue : *value;
10591071
}
10601072

10611073
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
@@ -1074,13 +1086,13 @@ Value const* Value::find(char const* key, char const* cend) const
10741086
const Value& Value::operator[](const char* key) const
10751087
{
10761088
Value const* found = find(key, key + strlen(key));
1077-
if (!found) return nullRef;
1089+
if (!found) return nullSingleton();
10781090
return *found;
10791091
}
10801092
Value const& Value::operator[](JSONCPP_STRING const& key) const
10811093
{
10821094
Value const* found = find(key.data(), key.data() + key.length());
1083-
if (!found) return nullRef;
1095+
if (!found) return nullSingleton();
10841096
return *found;
10851097
}
10861098

@@ -1103,7 +1115,7 @@ Value& Value::operator[](const CppTL::ConstString& key) {
11031115
Value const& Value::operator[](CppTL::ConstString const& key) const
11041116
{
11051117
Value const* found = find(key.c_str(), key.end_c_str());
1106-
if (!found) return nullRef;
1118+
if (!found) return nullSingleton();
11071119
return *found;
11081120
}
11091121
#endif
@@ -1151,7 +1163,7 @@ Value Value::removeMember(const char* key)
11511163
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
11521164
"in Json::Value::removeMember(): requires objectValue");
11531165
if (type_ == nullValue)
1154-
return nullRef;
1166+
return nullSingleton();
11551167

11561168
Value removed; // null
11571169
removeMember(key, key + strlen(key), &removed);
@@ -1538,7 +1550,7 @@ const Value& Path::resolve(const Value& root) const {
15381550
// Error: unable to resolve path (object value expected at position...)
15391551
}
15401552
node = &((*node)[arg.key_]);
1541-
if (node == &Value::nullRef) {
1553+
if (node == &Value::nullSingleton()) {
15421554
// Error: unable to resolve path (object has no member named '' at
15431555
// position...)
15441556
}
@@ -1559,7 +1571,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
15591571
if (!node->isObject())
15601572
return defaultValue;
15611573
node = &((*node)[arg.key_]);
1562-
if (node == &Value::nullRef)
1574+
if (node == &Value::nullSingleton())
15631575
return defaultValue;
15641576
}
15651577
}

0 commit comments

Comments
 (0)