Skip to content

Commit afd9cef

Browse files
committed
Removed experimental ValueAllocator, it caused static initialization/destruction order issues (bug #2934500). The DefaultValueAllocator has been inlined in code.
1 parent d38ba2a commit afd9cef

5 files changed

Lines changed: 46 additions & 112 deletions

File tree

NEWS.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,10 @@
1212
Notes: you need to setup the environment by running vcvars32.bat
1313
(e.g. MSVC 2008 command prompt in start menu) before running scons.
1414

15+
* Value
16+
17+
- Removed experimental ValueAllocator, it caused static
18+
initialization/destruction order issues (bug #2934500).
19+
The DefaultValueAllocator has been inlined in code.
20+
1521

include/json/forwards.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ namespace Json {
2626
class ValueIterator;
2727
class ValueConstIterator;
2828
#ifdef JSON_VALUE_USE_INTERNAL_MAP
29-
class ValueAllocator;
3029
class ValueMapAllocator;
3130
class ValueInternalLink;
3231
class ValueInternalArray;

include/json/value.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -513,26 +513,7 @@ namespace Json {
513513
Args args_;
514514
};
515515

516-
/** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
517-
*
518-
* - makeMemberName() and releaseMemberName() are called to respectively duplicate and
519-
* free an Json::objectValue member name.
520-
* - duplicateStringValue() and releaseStringValue() are called similarly to
521-
* duplicate and free a Json::stringValue value.
522-
*/
523-
class ValueAllocator
524-
{
525-
public:
526-
enum { unknown = (unsigned)-1 };
527-
528-
virtual ~ValueAllocator();
529516

530-
virtual char *makeMemberName( const char *memberName ) = 0;
531-
virtual void releaseMemberName( char *memberName ) = 0;
532-
virtual char *duplicateStringValue( const char *value,
533-
unsigned int length = unknown ) = 0;
534-
virtual void releaseStringValue( char *value ) = 0;
535-
};
536517

537518
#ifdef JSON_VALUE_USE_INTERNAL_MAP
538519
/** \brief Allocator to customize Value internal map.

src/lib_json/json_internalmap.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ ValueInternalMap::setNewItem( const char *key,
415415
ValueInternalLink *link,
416416
BucketIndex index )
417417
{
418-
char *duplicatedKey = valueAllocator()->makeMemberName( key );
418+
char *duplicatedKey = makeMemberName( key );
419419
++itemCount_;
420420
link->keys_[index] = duplicatedKey;
421421
link->items_[index].setItemUsed();

src/lib_json/json_value.cpp

Lines changed: 39 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -24,91 +24,39 @@ const Int Value::minInt = Int( ~(UInt(-1)/2) );
2424
const Int Value::maxInt = Int( UInt(-1)/2 );
2525
const UInt Value::maxUInt = UInt(-1);
2626

27-
// A "safe" implementation of strdup. Allow null pointer to be passed.
28-
// Also avoid warning on msvc80.
29-
//
30-
//inline char *safeStringDup( const char *czstring )
31-
//{
32-
// if ( czstring )
33-
// {
34-
// const size_t length = (unsigned int)( strlen(czstring) + 1 );
35-
// char *newString = static_cast<char *>( malloc( length ) );
36-
// memcpy( newString, czstring, length );
37-
// return newString;
38-
// }
39-
// return 0;
40-
//}
41-
//
42-
//inline char *safeStringDup( const std::string &str )
43-
//{
44-
// if ( !str.empty() )
45-
// {
46-
// const size_t length = str.length();
47-
// char *newString = static_cast<char *>( malloc( length + 1 ) );
48-
// memcpy( newString, str.c_str(), length );
49-
// newString[length] = 0;
50-
// return newString;
51-
// }
52-
// return 0;
53-
//}
27+
/// Unknown size marker
28+
enum { unknown = (unsigned)-1 };
5429

55-
ValueAllocator::~ValueAllocator()
56-
{
57-
}
5830

59-
class DefaultValueAllocator : public ValueAllocator
31+
/** Duplicates the specified string value.
32+
* @param value Pointer to the string to duplicate. Must be zero-terminated if
33+
* length is "unknown".
34+
* @param length Length of the value. if equals to unknown, then it will be
35+
* computed using strlen(value).
36+
* @return Pointer on the duplicate instance of string.
37+
*/
38+
static inline char *
39+
duplicateStringValue( const char *value,
40+
unsigned int length = unknown )
6041
{
61-
public:
62-
virtual ~DefaultValueAllocator()
63-
{
64-
}
65-
66-
virtual char *makeMemberName( const char *memberName )
67-
{
68-
return duplicateStringValue( memberName );
69-
}
70-
71-
virtual void releaseMemberName( char *memberName )
72-
{
73-
releaseStringValue( memberName );
74-
}
75-
76-
virtual char *duplicateStringValue( const char *value,
77-
unsigned int length = unknown )
78-
{
79-
//@todo invesgate this old optimization
80-
//if ( !value || value[0] == 0 )
81-
// return 0;
82-
83-
if ( length == unknown )
84-
length = (unsigned int)strlen(value);
85-
char *newString = static_cast<char *>( malloc( length + 1 ) );
86-
memcpy( newString, value, length );
87-
newString[length] = 0;
88-
return newString;
89-
}
42+
if ( length == unknown )
43+
length = (unsigned int)strlen(value);
44+
char *newString = static_cast<char *>( malloc( length + 1 ) );
45+
memcpy( newString, value, length );
46+
newString[length] = 0;
47+
return newString;
48+
}
9049

91-
virtual void releaseStringValue( char *value )
92-
{
93-
if ( value )
94-
free( value );
95-
}
96-
};
9750

98-
static ValueAllocator *&valueAllocator()
51+
/** Free the string duplicated by duplicateStringValue().
52+
*/
53+
static inline void
54+
releaseStringValue( char *value )
9955
{
100-
static DefaultValueAllocator defaultAllocator;
101-
static ValueAllocator *valueAllocator = &defaultAllocator;
102-
return valueAllocator;
56+
if ( value )
57+
free( value );
10358
}
10459

105-
static struct DummyValueAllocatorInitializer {
106-
DummyValueAllocatorInitializer()
107-
{
108-
valueAllocator(); // ensure valueAllocator() statics are initialized before main().
109-
}
110-
} dummyValueAllocatorInitializer;
111-
11260

11361

11462
// //////////////////////////////////////////////////////////////////
@@ -143,19 +91,19 @@ Value::CommentInfo::CommentInfo()
14391
Value::CommentInfo::~CommentInfo()
14492
{
14593
if ( comment_ )
146-
valueAllocator()->releaseStringValue( comment_ );
94+
releaseStringValue( comment_ );
14795
}
14896

14997

15098
void
15199
Value::CommentInfo::setComment( const char *text )
152100
{
153101
if ( comment_ )
154-
valueAllocator()->releaseStringValue( comment_ );
102+
releaseStringValue( comment_ );
155103
JSON_ASSERT( text );
156104
JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
157105
// It seems that /**/ style comments are acceptable as well.
158-
comment_ = valueAllocator()->duplicateStringValue( text );
106+
comment_ = duplicateStringValue( text );
159107
}
160108

161109

@@ -178,15 +126,15 @@ Value::CZString::CZString( int index )
178126
}
179127

180128
Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
181-
: cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
129+
: cstr_( allocate == duplicate ? duplicateStringValue(cstr)
182130
: cstr )
183131
, index_( allocate )
184132
{
185133
}
186134

187135
Value::CZString::CZString( const CZString &other )
188136
: cstr_( other.index_ != noDuplication && other.cstr_ != 0
189-
? valueAllocator()->makeMemberName( other.cstr_ )
137+
? duplicateStringValue( other.cstr_ )
190138
: other.cstr_ )
191139
, index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
192140
: other.index_ )
@@ -196,7 +144,7 @@ Value::CZString::CZString( const CZString &other )
196144
Value::CZString::~CZString()
197145
{
198146
if ( cstr_ && index_ == duplicate )
199-
valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
147+
releaseStringValue( const_cast<char *>( cstr_ ) );
200148
}
201149

202150
void
@@ -348,7 +296,7 @@ Value::Value( const char *value )
348296
, itemIsUsed_( 0 )
349297
#endif
350298
{
351-
value_.string_ = valueAllocator()->duplicateStringValue( value );
299+
value_.string_ = duplicateStringValue( value );
352300
}
353301

354302

@@ -361,8 +309,8 @@ Value::Value( const char *beginValue,
361309
, itemIsUsed_( 0 )
362310
#endif
363311
{
364-
value_.string_ = valueAllocator()->duplicateStringValue( beginValue,
365-
UInt(endValue - beginValue) );
312+
value_.string_ = duplicateStringValue( beginValue,
313+
UInt(endValue - beginValue) );
366314
}
367315

368316

@@ -374,8 +322,8 @@ Value::Value( const std::string &value )
374322
, itemIsUsed_( 0 )
375323
#endif
376324
{
377-
value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
378-
(unsigned int)value.length() );
325+
value_.string_ = duplicateStringValue( value.c_str(),
326+
(unsigned int)value.length() );
379327

380328
}
381329

@@ -400,7 +348,7 @@ Value::Value( const CppTL::ConstString &value )
400348
, itemIsUsed_( 0 )
401349
#endif
402350
{
403-
value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
351+
value_.string_ = duplicateStringValue( value, value.length() );
404352
}
405353
# endif
406354

@@ -434,7 +382,7 @@ Value::Value( const Value &other )
434382
case stringValue:
435383
if ( other.value_.string_ )
436384
{
437-
value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
385+
value_.string_ = duplicateStringValue( other.value_.string_ );
438386
allocated_ = true;
439387
}
440388
else
@@ -481,7 +429,7 @@ Value::~Value()
481429
break;
482430
case stringValue:
483431
if ( allocated_ )
484-
valueAllocator()->releaseStringValue( value_.string_ );
432+
releaseStringValue( value_.string_ );
485433
break;
486434
#ifndef JSON_VALUE_USE_INTERNAL_MAP
487435
case arrayValue:

0 commit comments

Comments
 (0)