Index: third_party/protobuf/src/google/protobuf/dynamic_message.cc |
=================================================================== |
--- third_party/protobuf/src/google/protobuf/dynamic_message.cc (revision 216642) |
+++ third_party/protobuf/src/google/protobuf/dynamic_message.cc (working copy) |
@@ -123,8 +123,10 @@ |
case FD::CPPTYPE_FLOAT : return sizeof(float ); |
case FD::CPPTYPE_BOOL : return sizeof(bool ); |
case FD::CPPTYPE_ENUM : return sizeof(int ); |
- case FD::CPPTYPE_MESSAGE: return sizeof(Message*); |
+ case FD::CPPTYPE_MESSAGE: |
+ return sizeof(Message*); |
+ |
case FD::CPPTYPE_STRING: |
switch (field->options().ctype()) { |
default: // TODO(kenton): Support other string reps. |
@@ -178,7 +180,17 @@ |
// important (the prototype must be deleted *before* the offsets). |
scoped_array<int> offsets; |
scoped_ptr<const GeneratedMessageReflection> reflection; |
- scoped_ptr<const DynamicMessage> prototype; |
+ // Don't use a scoped_ptr to hold the prototype: the destructor for |
+ // DynamicMessage needs to know whether it is the prototype, and does so by |
+ // looking back at this field. This would assume details about the |
+ // implementation of scoped_ptr. |
+ const DynamicMessage* prototype; |
+ |
+ TypeInfo() : prototype(NULL) {} |
+ |
+ ~TypeInfo() { |
+ delete prototype; |
+ } |
}; |
DynamicMessage(const TypeInfo* type_info); |
@@ -196,6 +208,14 @@ |
Metadata GetMetadata() const; |
+ // We actually allocate more memory than sizeof(*this) when this |
+ // class's memory is allocated via the global operator new. Thus, we need to |
+ // manually call the global operator delete. Calling the destructor is taken |
+ // care of for us. |
+ static void operator delete(void* ptr) { |
+ ::operator delete(ptr); |
+ } |
+ |
private: |
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); |
@@ -368,11 +388,12 @@ |
break; |
} |
} |
- } else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) && |
- !is_prototype()) { |
- Message* message = *reinterpret_cast<Message**>(field_ptr); |
- if (message != NULL) { |
- delete message; |
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
+ if (!is_prototype()) { |
+ Message* message = *reinterpret_cast<Message**>(field_ptr); |
+ if (message != NULL) { |
+ delete message; |
+ } |
} |
} |
} |
@@ -403,7 +424,7 @@ |
} |
Message* DynamicMessage::New() const { |
- void* new_base = reinterpret_cast<uint8*>(operator new(type_info_->size)); |
+ void* new_base = operator new(type_info_->size); |
memset(new_base, 0, type_info_->size); |
return new(new_base) DynamicMessage(type_info_); |
} |
@@ -465,7 +486,7 @@ |
const DynamicMessage::TypeInfo** target = &prototypes_->map_[type]; |
if (*target != NULL) { |
// Already exists. |
- return (*target)->prototype.get(); |
+ return (*target)->prototype; |
} |
DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo; |
@@ -533,13 +554,13 @@ |
void* base = operator new(size); |
memset(base, 0, size); |
DynamicMessage* prototype = new(base) DynamicMessage(type_info); |
- type_info->prototype.reset(prototype); |
+ type_info->prototype = prototype; |
// Construct the reflection object. |
type_info->reflection.reset( |
new GeneratedMessageReflection( |
type_info->type, |
- type_info->prototype.get(), |
+ type_info->prototype, |
type_info->offsets.get(), |
type_info->has_bits_offset, |
type_info->unknown_fields_offset, |