Use a Myers Singleton for null
Avoid some static initialization problems.
From @marklakata
See #488
diff --git a/include/json/value.h b/include/json/value.h
index 4c29382..fb88c18 100644
--- a/include/json/value.h
+++ b/include/json/value.h
@@ -190,6 +190,8 @@
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
+ static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
+
/// Minimum signed integer value that can be stored in a Json::Value.
static const LargestInt minLargestInt;
/// Maximum signed integer value that can be stored in a Json::Value.
diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index e195594..1d86883 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -31,10 +31,22 @@
#else
#define ALIGNAS(byte_alignment)
#endif
-static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-const unsigned char& kNullRef = kNull[0];
-const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
-const Value& Value::nullRef = null;
+//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+//const unsigned char& kNullRef = kNull[0];
+//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+//const Value& Value::nullRef = null;
+
+// static
+Value const& Value::nullSingleton()
+{
+ static Value const* nullStatic = new Value;
+ return *nullStatic;
+}
+
+// for backwards compatibility, we'll leave these global references around, but DO NOT
+// use them in JSONCPP library code any more!
+Value const& Value::null = Value::nullSingleton();
+Value const& Value::nullRef = Value::nullSingleton();
const Int Value::minInt = Int(~(UInt(-1) / 2));
const Int Value::maxInt = Int(UInt(-1) / 2);
@@ -972,7 +984,7 @@
if (it != value_.map_->end() && (*it).first == key)
return (*it).second;
- ObjectValues::value_type defaultValue(key, nullRef);
+ ObjectValues::value_type defaultValue(key, nullSingleton());
it = value_.map_->insert(it, defaultValue);
return (*it).second;
}
@@ -989,11 +1001,11 @@
type_ == nullValue || type_ == arrayValue,
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
if (type_ == nullValue)
- return nullRef;
+ return nullSingleton();
CZString key(index);
ObjectValues::const_iterator it = value_.map_->find(key);
if (it == value_.map_->end())
- return nullRef;
+ return nullSingleton();
return (*it).second;
}
@@ -1027,7 +1039,7 @@
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
- ObjectValues::value_type defaultValue(actualKey, nullRef);
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
@@ -1047,7 +1059,7 @@
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
- ObjectValues::value_type defaultValue(actualKey, nullRef);
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
@@ -1055,7 +1067,7 @@
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
const Value* value = &((*this)[index]);
- return value == &nullRef ? defaultValue : *value;
+ return value == &nullSingleton() ? defaultValue : *value;
}
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
@@ -1074,13 +1086,13 @@
const Value& Value::operator[](const char* key) const
{
Value const* found = find(key, key + strlen(key));
- if (!found) return nullRef;
+ if (!found) return nullSingleton();
return *found;
}
Value const& Value::operator[](JSONCPP_STRING const& key) const
{
Value const* found = find(key.data(), key.data() + key.length());
- if (!found) return nullRef;
+ if (!found) return nullSingleton();
return *found;
}
@@ -1103,7 +1115,7 @@
Value const& Value::operator[](CppTL::ConstString const& key) const
{
Value const* found = find(key.c_str(), key.end_c_str());
- if (!found) return nullRef;
+ if (!found) return nullSingleton();
return *found;
}
#endif
@@ -1151,7 +1163,7 @@
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue)
- return nullRef;
+ return nullSingleton();
Value removed; // null
removeMember(key, key + strlen(key), &removed);
@@ -1538,7 +1550,7 @@
// Error: unable to resolve path (object value expected at position...)
}
node = &((*node)[arg.key_]);
- if (node == &Value::nullRef) {
+ if (node == &Value::nullSingleton()) {
// Error: unable to resolve path (object has no member named '' at
// position...)
}
@@ -1559,7 +1571,7 @@
if (!node->isObject())
return defaultValue;
node = &((*node)[arg.key_]);
- if (node == &Value::nullRef)
+ if (node == &Value::nullSingleton())
return defaultValue;
}
}