|
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
[an error occurred while processing this directive]
How It Works The C++ compiler will automatically call the overloaded functions instead of the built-in ones. Comments The quality and details of the delete[] and new[] operators vary significantly between compiler vendors. Try running the sample code to see what your compiler generates. All sample listings here are initially compiled with Borland C++, and are tested with DJGPP (a GNU compiler for DOS, including a 32-bit DOS extender). The program leaves the memory statistics in the file memstats.txt, and the results vary between even these two compilers. The following listing shows the memstats.txt file generated by a program compiled with Borland C++ 5.01A. Notice that the bytes allocated and deleted do not match, but the calls do. Memory allocation statistics : (the numbers below should match) Bytes Allocated : 600012 Bytes Deleted : 300024 Calls to new : 25001 Calls to new[] : 1 Calls to delete : 25001 Calls to delete[]:1 The following is a memstats.txt file generated by a program compiled with DJGPP using GCC 2.81: Memory allocation statistics : (the numbers below should match) Bytes Allocated : 600016 Bytes Deleted : 600016 Calls to new : 25001 Calls to new[] : 1 Calls to delete : 25001 Calls to delete[]:1 As you can see by the output of the programs, the compilers used in this case differed in how they handled the delete operators as well as how they handled the actual size of the Sample_Data class. The difference can be attributed to byte-alignment settings. The GNU compiler seems to default to 8-byte alignment (which is the fastest for Pentium and later processors) in this case, and the Borland compiler seems to default to 4-byte alignment. However, the compilers seem to agree on array sizes, and align them on 8-byte boundaries. Code Listings for Chapter 12 The following listing, ex1\newdel.cpp, overloads the new and delete operators: // File: overnew.cpp // Example for C++ How-To // Shows how to overload new and delete to implement a simple memory // statistics keeper. // Copyright 1998, Jan Walter // NO WARRANTY. If this code breaks you get to keep both pieces. // Compiler verificiation: // Borland C++ 5.01A: Yes // DJGPP 2.01 w. GCC 2.81 : Yes // Watcom 10.5: Not Tried // Microsoft VC++ 5: Not Tried // GCC 2.7.2/Linux: Not tried // GCC/EGCS/Linux: Not tried #include <iostream.h> #include <fstream.h> #include <stddef.h> #ifdef __BORLANDC__ #pragma hdrstop #endif #include <string> #include <stdexcept> // standard exception classes using namespace std ; //********************************************************************* // Memory statistics class //********************************************************************* class MemStats { private: unsigned BytesAllocated ; unsigned BytesDeleted ; unsigned CallsToNew ; unsigned CallsToDel ; fstream StatsFile; public: MemStats() : BytesAllocated(0), BytesDeleted(0), CallsToNew(0), CallsToDel(0) { StatsFile.open( memstats.txt, ios::out ) ; if( !StatsFile ) throw runtime_error( Could not open memstats.txt ) ; } MemStats( const string& filename ) : BytesAllocated(0), BytesDeleted(0), CallsToNew(0), CallsToDel(0) { StatsFile.open( filename.c_str() , ios::out ) ; if( !StatsFile ) throw runtime_error( Could not open user-defined file. ) ; } // these functions can be expanded to do all sorts of other things, // like print more info into the output file, time and date, etc. // or keep track of the allocated chunks of memory in an associative // array. void newcalled( size_t size ) { CallsToNew++ ; BytesAllocated += size ; } void delcalled( size_t size ) { CallsToDel++ ; BytesDeleted += size ; } ~MemStats() { StatsFile << endl << Memory allocation statistics : << endl << (the numbers below should match) << endl << endl << Bytes Allocated : << BytesAllocated << endl << Bytes Deleted : << BytesDeleted << endl << Calls to new : << CallsToNew << endl << Calls to delete : << CallsToDel << endl << endl ; StatsFile.close() ; // explicitly close file to make // doubly sure. } } ; //********************************************************************* // an interesting side note: // we cannot easily catch exceptions thrown by the constructor of // a global object - above the constructor throws a runtime_error // exception object if it cannot open the file in the constructor. // If this is true, the program will abort with some message like // abnormal program termination or Abort! MemStats stats ; //********************************************************************* // Sample Data class - nothing special, just an example //********************************************************************* class Sample_Data { int S_int ; double S_double ; public: Sample_Data() : S_int(0), S_double(0.0) { } Sample_Data( int a, double b = 0.0) { S_int = a ; S_double = b ; } Sample_Data( double b, int a = 0 ) { S_double = b ; S_int = a ; } Sample_Data( Sample_Data& copyfrom ) { S_int = copyfrom.S_int ; S_double = copyfrom.S_double ; } Sample_Data& operator=( const Sample_Data& copyfrom ) { S_int = copyfrom.S_int ; S_double = copyfrom.S_double ; return *this ; } Sample_Data& operator++() { S_int++ ; return *this ; } void* operator new( size_t size ) { stats.newcalled( size ) ; return (void*) ::new char[size] ; // allocate specified number of bytes // with the actual new operator } void operator delete( void* mem, size_t size ) { stats.delcalled( size ); ::delete[] mem ; } // friend functions friend ostream& operator<<( ostream& s, const Sample_Data& data ); }; //********************************************************************* ostream& operator<<( ostream& s, const Sample_Data& data ) { s << data.S_int << << data.S_double ; return s ; } //********************************************************************* int main( int, char** ) { const int array_size = 50000 ; // allocate our sample data cout << Size of Sample_Data: << sizeof(Sample_Data) << endl ; // declare one object Sample_Data a( 50 , 12.555 ); // instantiate an object dynamically Sample_Data* p = new Sample_Data( 21 ) ; // declare an array Sample_Data* DataArray = new Sample_Data[array_size] ; // declare an array of pointers Sample_Data* PDataArray[array_size] ; // initialize the array for (int i = 0 ; i < array_size ; i++ ) PDataArray[i] = new Sample_Data(i) ; // Now work with the data some DataArray[0] = a ; for( int i = 1; i < array_size ; i++ ) { DataArray[i] = ++DataArray[i-1] ; //cout << DataArray[i] << endl ; } ++*p ; cout << *p << endl ; // and clean up dynamically allocated stuff. delete p ; delete[] DataArray ; for (int i = 0 ; i < array_size ; i++ ) delete PDataArray[i] ; return 0; } // end of file
|
![]() |
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.
|