diff --git a/Makefile.am b/Makefile.am index 2674f02c..315a4610 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,6 +71,7 @@ src_libairbag_la_SOURCES = \ src/processor/postfix_evaluator-inl.h \ src/processor/range_map.h \ src/processor/range_map-inl.h \ + src/processor/scoped_ptr.h \ src/processor/source_line_resolver.cc \ src/processor/source_line_resolver.h \ src/processor/stack_frame_info.h \ diff --git a/Makefile.in b/Makefile.in index 88bfdad9..d693a496 100644 --- a/Makefile.in +++ b/Makefile.in @@ -371,6 +371,7 @@ src_libairbag_la_SOURCES = \ src/processor/postfix_evaluator-inl.h \ src/processor/range_map.h \ src/processor/range_map-inl.h \ + src/processor/scoped_ptr.h \ src/processor/source_line_resolver.cc \ src/processor/source_line_resolver.h \ src/processor/stack_frame_info.h \ diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index 2d3dce81..068f47d0 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -49,17 +49,16 @@ typedef SSIZE_T ssize_t; #endif // _WIN32 #include -#include #include #include "processor/minidump.h" #include "processor/range_map-inl.h" +#include "processor/scoped_ptr.h" namespace google_airbag { -using std::auto_ptr; using std::vector; @@ -163,7 +162,7 @@ static inline void Swap(MDGUID* guid) { // of making it a dependency when we don't care about anything but UTF-16. static string* UTF16ToUTF8(const vector& in, bool swap) { - auto_ptr out(new string()); + scoped_ptr out(new string()); // Set the string's initial capacity to the number of UTF-16 characters, // because the UTF-8 representation will always be at least this long. @@ -288,7 +287,7 @@ bool MinidumpContext::Read(u_int32_t expected_size) { if (expected_size != sizeof(MDRawContextX86)) return false; - auto_ptr context_x86(new MDRawContextX86()); + scoped_ptr context_x86(new MDRawContextX86()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -355,7 +354,7 @@ bool MinidumpContext::Read(u_int32_t expected_size) { if (expected_size != sizeof(MDRawContextPPC)) return false; - auto_ptr context_ppc(new MDRawContextPPC()); + scoped_ptr context_ppc(new MDRawContextPPC()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -647,7 +646,7 @@ const u_int8_t* MinidumpMemoryRegion::GetMemory() { return NULL; // TODO(mmentovai): verify rational size! - auto_ptr< vector > memory( + scoped_ptr< vector > memory( new vector(descriptor_->memory.data_size)); if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) @@ -817,7 +816,7 @@ MinidumpContext* MinidumpThread::GetContext() { if (!minidump_->SeekSet(thread_.thread_context.rva)) return NULL; - auto_ptr context(new MinidumpContext(minidump_)); + scoped_ptr context(new MinidumpContext(minidump_)); if (!context->Read(thread_.thread_context.data_size)) return NULL; @@ -916,7 +915,7 @@ bool MinidumpThreadList::Read(u_int32_t expected_size) { } // TODO(mmentovai): verify rational size! - auto_ptr threads( + scoped_ptr threads( new MinidumpThreads(thread_count, MinidumpThread(minidump_))); for (unsigned int thread_index = 0; @@ -1086,7 +1085,7 @@ const u_int8_t* MinidumpModule::GetCVRecord() { // variable-sized due to their pdb_file_name fields; these structures // are not sizeof(MDCVInfoPDB70) or sizeof(MDCVInfoPDB20) and treating // them as such would result in incomplete structures or overruns. - auto_ptr< vector > cv_record( + scoped_ptr< vector > cv_record( new vector(module_.cv_record.data_size)); if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) @@ -1161,7 +1160,7 @@ const MDImageDebugMisc* MinidumpModule::GetMiscRecord() { // because the MDImageDebugMisc is variable-sized due to its data field; // this structure is not sizeof(MDImageDebugMisc) and treating it as such // would result in an incomplete structure or an overrun. - auto_ptr< vector > misc_record_mem( + scoped_ptr< vector > misc_record_mem( new vector(module_.misc_record.data_size)); MDImageDebugMisc* misc_record = reinterpret_cast(&(*misc_record_mem)[0]); @@ -1443,7 +1442,7 @@ bool MinidumpModuleList::Read(u_int32_t expected_size) { } // TODO(mmentovai): verify rational size! - auto_ptr modules( + scoped_ptr modules( new MinidumpModules(module_count, MinidumpModule(minidump_))); for (unsigned int module_index = 0; @@ -1557,7 +1556,8 @@ bool MinidumpMemoryList::Read(u_int32_t expected_size) { } // TODO(mmentovai): verify rational size! - auto_ptr descriptors(new MemoryDescriptors(region_count)); + scoped_ptr descriptors( + new MemoryDescriptors(region_count)); // Read the entire array in one fell swoop, instead of reading one entry // at a time in the loop. @@ -1566,7 +1566,7 @@ bool MinidumpMemoryList::Read(u_int32_t expected_size) { return false; } - auto_ptr regions( + scoped_ptr regions( new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_))); for (unsigned int region_index = 0; @@ -1720,7 +1720,7 @@ MinidumpContext* MinidumpException::GetContext() { if (!minidump_->SeekSet(exception_.thread_context.rva)) return NULL; - auto_ptr context(new MinidumpContext(minidump_)); + scoped_ptr context(new MinidumpContext(minidump_)); if (!context->Read(exception_.thread_context.data_size)) return NULL; @@ -2060,7 +2060,7 @@ bool Minidump::Read() { return false; // TODO(mmentovai): verify rational size! - auto_ptr directory( + scoped_ptr directory( new MinidumpDirectoryEntries(header_.stream_count)); // Read the entire array in one fell swoop, instead of reading one entry @@ -2069,7 +2069,7 @@ bool Minidump::Read() { sizeof(MDRawDirectory) * header_.stream_count)) return false; - auto_ptr stream_map(new MinidumpStreamMap()); + scoped_ptr stream_map(new MinidumpStreamMap()); for (unsigned int stream_index = 0; stream_index < header_.stream_count; @@ -2312,7 +2312,7 @@ T* Minidump::GetStream(T** stream) { if (!SeekToStreamType(stream_type, &stream_length)) return NULL; - auto_ptr new_stream(new T(this)); + scoped_ptr new_stream(new T(this)); if (!new_stream->Read(stream_length)) return NULL; diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index 20609fb6..8f6497e2 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -27,14 +27,11 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include - #include "google/minidump_processor.h" #include "processor/minidump.h" +#include "processor/scoped_ptr.h" #include "processor/stackwalker_x86.h" -using std::auto_ptr; - namespace google_airbag { MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier) @@ -71,7 +68,7 @@ CallStack* MinidumpProcessor::Process(const string &minidump_file) { return NULL; } - auto_ptr walker( + scoped_ptr walker( Stackwalker::StackwalkerForCPU(exception->GetContext(), thread_memory, dump.GetModuleList(), supplier_)); if (!walker.get()) { diff --git a/src/processor/minidump_processor_unittest.cc b/src/processor/minidump_processor_unittest.cc index ca02721e..283b67ed 100644 --- a/src/processor/minidump_processor_unittest.cc +++ b/src/processor/minidump_processor_unittest.cc @@ -30,18 +30,18 @@ // Unit test for MinidumpProcessor. Uses a pre-generated minidump and // corresponding symbol file, and checks the stack frames for correctness. -#include #include #include "google/call_stack.h" #include "google/minidump_processor.h" #include "google/stack_frame.h" #include "google/symbol_supplier.h" #include "processor/minidump.h" +#include "processor/scoped_ptr.h" -using std::auto_ptr; using std::string; using google_airbag::CallStack; using google_airbag::MinidumpProcessor; +using google_airbag::scoped_ptr; #define ASSERT_TRUE(cond) \ if (!(cond)) { \ @@ -79,7 +79,7 @@ static bool RunTests() { string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + "/src/processor/testdata/minidump2.dmp"; - auto_ptr stack(processor.Process(minidump_file)); + scoped_ptr stack(processor.Process(minidump_file)); ASSERT_TRUE(stack.get()); ASSERT_EQ(stack->frames()->size(), 4); diff --git a/src/processor/minidump_stackwalk.cc b/src/processor/minidump_stackwalk.cc index cd2cbe3d..1bcf2a66 100644 --- a/src/processor/minidump_stackwalk.cc +++ b/src/processor/minidump_stackwalk.cc @@ -35,16 +35,15 @@ #include #include -#include #include #include "google/call_stack.h" #include "google/stack_frame.h" #include "processor/minidump.h" +#include "processor/scoped_ptr.h" #include "processor/stackwalker_x86.h" -using std::auto_ptr; using std::string; using google_airbag::CallStack; using google_airbag::MemoryRegion; @@ -54,6 +53,7 @@ using google_airbag::MinidumpException; using google_airbag::MinidumpModuleList; using google_airbag::MinidumpThread; using google_airbag::MinidumpThreadList; +using google_airbag::scoped_ptr; using google_airbag::StackFrame; using google_airbag::Stackwalker; @@ -107,14 +107,14 @@ int main(int argc, char **argv) { exit(1); } - auto_ptr stackwalker( + scoped_ptr stackwalker( Stackwalker::StackwalkerForCPU(context, stack_memory, modules, NULL)); if (!stackwalker.get()) { fprintf(stderr, "Stackwalker::StackwalkerForCPU failed\n"); exit(1); } - auto_ptr stack(stackwalker->Walk()); + scoped_ptr stack(stackwalker->Walk()); unsigned int index; for (index = 0; index < stack->frames()->size(); ++index) { diff --git a/src/processor/range_map_unittest.cc b/src/processor/range_map_unittest.cc index 39fac6d0..af257cf0 100644 --- a/src/processor/range_map_unittest.cc +++ b/src/processor/range_map_unittest.cc @@ -34,14 +34,14 @@ #include #include -#include #include "processor/linked_ptr.h" #include "processor/range_map-inl.h" +#include "processor/scoped_ptr.h" -using std::auto_ptr; using google_airbag::linked_ptr; +using google_airbag::scoped_ptr; using google_airbag::RangeMap; @@ -331,7 +331,7 @@ bool RunTests() { // Maintain the range map in a pointer so that deletion can be meaningfully // tested. - auto_ptr range_map(new TestMap()); + scoped_ptr range_map(new TestMap()); // Run all of the test sets in sequence. unsigned int range_test_set_count = sizeof(range_test_sets) / diff --git a/src/processor/scoped_ptr.h b/src/processor/scoped_ptr.h new file mode 100644 index 00000000..59036492 --- /dev/null +++ b/src/processor/scoped_ptr.h @@ -0,0 +1,335 @@ +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. +// + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +// *** NOTE *** +// If your scoped_ptr is a class member of class FOO pointing to a +// forward declared type BAR (as shown below), then you MUST use a non-inlined +// version of the destructor. The destructor of a scoped_ptr (called from +// FOO's destructor) must have a complete definition of BAR in order to +// destroy it. Example: +// +// -- foo.h -- +// class BAR; +// +// class FOO { +// public: +// FOO(); +// ~FOO(); // Required for sources that instantiate class FOO to compile! +// +// private: +// scoped_ptr bar_; +// }; +// +// -- foo.cc -- +// #include "foo.h" +// FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. + +// scoped_ptr_malloc added by Google +// When one of these goes out of scope, instead of doing a delete or +// delete[], it calls free(). scoped_ptr_malloc is likely to see +// much more use than any other specializations. + +// release() added by Google +// Use this to conditionally transfer ownership of a heap-allocated object +// to the caller, usually on method success. + +#ifndef PROCESSOR_SCOPED_PTR_H__ +#define PROCESSOR_SCOPED_PTR_H__ + +#include // for std::ptrdiff_t +#include // for assert +#include // for free() decl + +namespace google_airbag { + +template +class scoped_ptr { + private: + + T* ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + public: + + typedef T element_type; + + explicit scoped_ptr(T* p = 0): ptr(p) {} + + ~scoped_ptr() { + typedef char type_must_be_complete[sizeof(T)]; + delete ptr; + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + delete ptr; + ptr = p; + } + } + + T& operator*() const { + assert(ptr != 0); + return *ptr; + } + + T* operator->() const { + assert(ptr != 0); + return ptr; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_ptr & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_ptr should have its own object + template bool operator==(scoped_ptr const& p) const; + template bool operator!=(scoped_ptr const& p) const; +}; + +template inline +void swap(scoped_ptr& a, scoped_ptr& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_ptr& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_ptr& b) { + return p != b.get(); +} + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template +class scoped_array { + private: + + T* ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + public: + + typedef T element_type; + + explicit scoped_array(T* p = 0) : ptr(p) {} + + ~scoped_array() { + typedef char type_must_be_complete[sizeof(T)]; + delete[] ptr; + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + delete [] ptr; + ptr = p; + } + } + + T& operator[](std::ptrdiff_t i) const { + assert(ptr != 0); + assert(i >= 0); + return ptr[i]; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_array & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_array should have its own object + template bool operator==(scoped_array const& p) const; + template bool operator!=(scoped_array const& p) const; +}; + +template inline +void swap(scoped_array& a, scoped_array& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_array& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_array& b) { + return p != b.get(); +} + + +// This class wraps the c library function free() in a class that can be +// passed as a template argument to scoped_ptr_malloc below. +class ScopedPtrMallocFree { + public: + inline void operator()(void* x) const { + free(x); + } +}; + +// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a +// second template argument, the functor used to free the object. + +template +class scoped_ptr_malloc { + private: + + T* ptr; + + scoped_ptr_malloc(scoped_ptr_malloc const &); + scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); + + public: + + typedef T element_type; + + explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} + + ~scoped_ptr_malloc() { + typedef char type_must_be_complete[sizeof(T)]; + free_((void*) ptr); + } + + void reset(T* p = 0) { + typedef char type_must_be_complete[sizeof(T)]; + + if (ptr != p) { + free_((void*) ptr); + ptr = p; + } + } + + T& operator*() const { + assert(ptr != 0); + return *ptr; + } + + T* operator->() const { + assert(ptr != 0); + return ptr; + } + + bool operator==(T* p) const { + return ptr == p; + } + + bool operator!=(T* p) const { + return ptr != p; + } + + T* get() const { + return ptr; + } + + void swap(scoped_ptr_malloc & b) { + T* tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + + T* release() { + T* tmp = ptr; + ptr = 0; + return tmp; + } + + private: + + // no reason to use these: each scoped_ptr_malloc should have its own object + template + bool operator==(scoped_ptr_malloc const& p) const; + template + bool operator!=(scoped_ptr_malloc const& p) const; + + static FreeProc const free_; +}; + +template +FP const scoped_ptr_malloc::free_ = FP(); + +template inline +void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) { + a.swap(b); +} + +template inline +bool operator==(T* p, const scoped_ptr_malloc& b) { + return p == b.get(); +} + +template inline +bool operator!=(T* p, const scoped_ptr_malloc& b) { + return p != b.get(); +} + +} // namespace google_airbag + +#endif // PROCESSOR_SCOPED_PTR_H__ diff --git a/src/processor/source_line_resolver.cc b/src/processor/source_line_resolver.cc index 8a6fad16..a6f9d740 100644 --- a/src/processor/source_line_resolver.cc +++ b/src/processor/source_line_resolver.cc @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include "processor/source_line_resolver.h" @@ -39,9 +38,9 @@ #include "processor/address_map-inl.h" #include "processor/contained_range_map-inl.h" #include "processor/range_map-inl.h" +#include "processor/scoped_ptr.h" #include "processor/stack_frame_info.h" -using std::auto_ptr; using std::map; using std::vector; using std::make_pair; @@ -278,7 +277,7 @@ StackFrameInfo* SourceLineResolver::Module::LookupAddress( stack_info_[STACK_INFO_FPO].RetrieveRange(address, &retrieved_info); } - auto_ptr frame_info; + scoped_ptr frame_info; if (retrieved_info.get()) { frame_info.reset(new StackFrameInfo()); frame_info->CopyFrom(*retrieved_info.get()); diff --git a/src/processor/source_line_resolver_unittest.cc b/src/processor/source_line_resolver_unittest.cc index e9ee9d91..3ac5ea01 100644 --- a/src/processor/source_line_resolver_unittest.cc +++ b/src/processor/source_line_resolver_unittest.cc @@ -28,16 +28,16 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include #include #include "processor/source_line_resolver.h" #include "google/stack_frame.h" #include "processor/linked_ptr.h" +#include "processor/scoped_ptr.h" #include "processor/stack_frame_info.h" -using std::auto_ptr; using std::string; using google_airbag::linked_ptr; +using google_airbag::scoped_ptr; using google_airbag::SourceLineResolver; using google_airbag::StackFrame; using google_airbag::StackFrameInfo; @@ -78,7 +78,7 @@ static bool RunTests() { StackFrame frame; frame.instruction = 0x1000; frame.module_name = "module1"; - auto_ptr frame_info(resolver.FillSourceLineInfo(&frame)); + scoped_ptr frame_info(resolver.FillSourceLineInfo(&frame)); ASSERT_EQ(frame.function_name, "Function1_1"); ASSERT_EQ(frame.source_file_name, "file1_1.cc"); ASSERT_EQ(frame.source_line, 44); diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index ffe258e7..358df8ac 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -34,14 +34,13 @@ // Author: Mark Mentovai -#include - #include "processor/stackwalker.h" #include "google/call_stack.h" #include "google/stack_frame.h" #include "google/symbol_supplier.h" #include "processor/linked_ptr.h" #include "processor/minidump.h" +#include "processor/scoped_ptr.h" #include "processor/source_line_resolver.h" #include "processor/stack_frame_info.h" #include "processor/stackwalker_ppc.h" @@ -49,8 +48,6 @@ namespace google_airbag { -using std::auto_ptr; - Stackwalker::Stackwalker(MemoryRegion *memory, MinidumpModuleList *modules, SymbolSupplier *supplier) @@ -61,7 +58,7 @@ Stackwalker::Stackwalker(MemoryRegion *memory, MinidumpModuleList *modules, CallStack* Stackwalker::Walk() { SourceLineResolver resolver; - auto_ptr stack(new CallStack()); + scoped_ptr stack(new CallStack()); // stack_frame_info parallels the CallStack. The vector is passed to the // GetCallerFrame function. It contains information that may be helpful @@ -72,7 +69,7 @@ CallStack* Stackwalker::Walk() { // no more. // Take ownership of the pointer returned by GetContextFrame. - auto_ptr frame(GetContextFrame()); + scoped_ptr frame(GetContextFrame()); while (frame.get()) { // frame already contains a good frame with properly set instruction and diff --git a/src/processor/stackwalker_selftest.cc b/src/processor/stackwalker_selftest.cc index 5c8f93bc..76136a64 100644 --- a/src/processor/stackwalker_selftest.cc +++ b/src/processor/stackwalker_selftest.cc @@ -38,7 +38,6 @@ #include -#include #include "google/airbag_types.h" #include "google/call_stack.h" @@ -46,10 +45,11 @@ #include "google/stack_frame_cpu.h" #include "processor/memory_region.h" #include "processor/minidump_format.h" +#include "processor/scoped_ptr.h" -using std::auto_ptr; using google_airbag::CallStack; using google_airbag::MemoryRegion; +using google_airbag::scoped_ptr; using google_airbag::StackFrame; using google_airbag::StackFramePPC; using google_airbag::StackFrameX86; @@ -218,7 +218,7 @@ static unsigned int CountCallerFrames() { StackwalkerPPC stackwalker = StackwalkerPPC(&context, &memory, NULL, NULL); #endif // __i386__ || __ppc__ - auto_ptr stack(stackwalker.Walk()); + scoped_ptr stack(stackwalker.Walk()); #ifdef PRINT_STACKS printf("\n");