horstman@sjsumcs.sjsu.edu (Cay Horstmann) (12/29/90)
Recently someone asked whether one can distinguish objects allocated with
new from those allocated on the stack, and it just occurred to me that this
is possible. Ignore this if the technique is an old hat, it is new to me.
Give class X a member int fromHeap and a static member int heapFlag. Define
all constructors X::X( ... ) to contain the lines
fromHeap = heapFlag;
heapFlag = 0;
and define X::operator new( size_t s ) as
{ heapFlag = 1;
return new char[s];
}
If x is any pointer of type X*, then x->fromHeap is true iff x is allocated
on the heap. I am using the fact that X::operator new is (acts like?) a
static member function and hence can access static members of X.
Is this legal? Is it in the spirit of the language? Is it useful? CAN I PATENT
IT?
Happy new year,
Cay
psaripe@cadev5.intel.com (Phani Saripella ~) (01/05/91)
In article <1990Dec29.013620.23761@sjsumcs.sjsu.edu! horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes:
!Recently someone asked whether one can distinguish objects allocated with
!new from those allocated on the stack, and it just occurred to me that this
!is possible. Ignore this if the technique is an old hat, it is new to me.
!
!Give class X a member int fromHeap and a static member int heapFlag. Define
!all constructors X::X( ... ) to contain the lines
! fromHeap = heapFlag;
! heapFlag = 0;
!and define X::operator new( size_t s ) as
Only one catch here. operator new *CANNOT* be overloaded ( nor can delete
for that matter)
! { heapFlag = 1;
! return new char[s];
! }
!
!If x is any pointer of type X*, then x->fromHeap is true iff x is allocated
!on the heap. I am using the fact that X::operator new is (acts like?) a
!static member function and hence can access static members of X.
!
!Is this legal? Is it in the spirit of the language? Is it useful? CAN I PATENT
!IT?
!
!Happy new year,
!
!Cay
Phani
wlp@calmasd.Prime.COM (Walter Peterson) (01/05/91)
In article <1598@inews.intel.com> psaripe@cadev5.UUCP (Phani Saripella ~) writes: >Only one catch here. operator new *CANNOT* be overloaded ( nor can delete >for that matter) You are woefully behind the times! It was true that prior to Release 2.0 operators new and delete could not be overloaded, but ever since then new and delete have been overloadable. That change occured quite a long time ago. I attribute a good bit of this confusion to the plethora of poorly written, poorly researched and out of date C++ books that are currently on the market. Just because someone found a publisher does not mean that they know what they are talking about. Nor does the fact that a book is offered for sale mean that either the bookseller or publisher care if it is obsolete. Until the ANSI standard is promulgated the most authoritative source is: Ellis, Margaret A. & Bjarne Stroustrup, "The Annotated C++ Reference Manual", Addison-Wesley, Reading, MA, 1990 ISBN 0-201-51459-1 This is the Base Document for the ANSI committee. -- Walter L. Peterson | ______ Internet : wlp@calmasd.Prime.COM | \ / CompuServe : 70441,3177 | \ / Silence = Death "The opinions expressed here are my own." | \/
peterli@ux5.lbl.gov (01/05/91)
In article <1990Dec29.013620.23761@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes: >Recently someone asked whether one can distinguish objects allocated with >new from those allocated on the stack, and it just occurred to me that this >is possible. Ignore this if the technique is an old hat, it is new to me. > >Cay For platforms with uniform address space and where stack and data grows toward each other, then you should be able to use sbrk(0). Read man pages end(3) and sbrk(2). Peter Li
aed@netcom.UUCP (Andrew Davidson) (01/06/91)
It is possible to overload the new and delete operators. "A class memeber instance of opterator new must specify a retutn tupe of woid* and take a first argument of the system tupedf size_t, defined in the stddef.h system header file. this argument is automaticlally initalized by the compiler with the size of the class type in bytes." Stanley Lippman "C++ Primer" "the delete operator must have a first argument of thpe void*. A second argumment of the predefined system typedef size_t may be specified (rember to includee stddef.h) If present it is initialized implicityly wiht the sze in bytes of the object addressed by the first argument. the delete operator must have a return type of void." Stanley Lippman "C++ Primer" pages 262 - 266 andy -- ----------------------------------------------------------------- "bede-bede-bede Thats all Folks" Porky Pig Andy Davidson Woodside CA. aed@netcom -----------------------------------------------------------------
jgro@lia (Jeremy Grodberg) (01/08/91)
In article <1990Dec29.013620.23761@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes: >Give class X a member int fromHeap and a static member int heapFlag. Define >all constructors X::X( ... ) to contain the lines > fromHeap = heapFlag; > heapFlag = 0; >and define X::operator new( size_t s ) as > { heapFlag = 1; > return new char[s]; > } > >If x is any pointer of type X*, then x->fromHeap is true iff x is allocated >on the heap. I am using the fact that X::operator new is (acts like?) a >static member function and hence can access static members of X. > >Is this legal? Is it in the spirit of the language? Is it useful? CAN I PATENT >IT? Yes. Maybe. No. No. The real problem here is that whle this will work for X* x = new X(...); It will not catch X* x = new X[10]; since that will use ::new, not X::new. -- Jeremy Grodberg "I don't feel witty today. Don't bug me." jgro@lia.com
grahamd@otc.otca.oz.au (Graham Dumpleton) (01/10/91)
In article <1991Jan7.231403.318@lia>, jgro@lia (Jeremy Grodberg) writes: |> In article <1990Dec29.013620.23761@sjsumcs.sjsu.edu> horstman@sjsumcs.SJSU.EDU (Cay Horstmann) writes: |> >Give class X a member int fromHeap and a static member int heapFlag. Define |> >all constructors X::X( ... ) to contain the lines |> > fromHeap = heapFlag; |> > heapFlag = 0; |> >and define X::operator new( size_t s ) as |> > { heapFlag = 1; |> > return new char[s]; |> > } |> > |> >If x is any pointer of type X*, then x->fromHeap is true iff x is allocated |> >on the heap. I am using the fact that X::operator new is (acts like?) a |> >static member function and hence can access static members of X. |> > |> >Is this legal? Is it in the spirit of the language? Is it useful? CAN I PATENT |> >IT? |> |> Yes. |> Maybe. |> No. |> No. |> |> |> The real problem here is that whle this will work for |> |> X* x = new X(...); |> |> It will not catch |> |> X* x = new X[10]; |> |> since that will use ::new, not X::new. |> |> -- |> Jeremy Grodberg "I don't feel witty today. Don't bug me." |> jgro@lia.com Depending on the use to which you are putting this information, knowing that something is created within an array of objects on the heap is not required and if it was possible to find this out, would have to be distinguished from not being in an array. Consider a class for performing reference counting; something like that defined in the InterViews class library. class Resource { private: u_int myNumRefs; protected: Resource() : myNumRefs(0) { } virtual ~Resource() { } public: void reference() { myNumRefs++; } void unReference() { myNumRefs--; if (myNumRefs == 0) delete this; } u_int numRefs() { return myNumRefs; } }; One problem with this class; as it is, is that if you create an instance of a class derived from it on the stack, then you can run into problems. class Foo : public Resource { ... }; void func() { Foo foo; foo.reference(); foo.unReference(); // foo destroyed. } // foo destroyed again. A destructor which gets called twice could cause major problems in a program depending on what it actually did. Yes, you could say that you must always create instances of a class derived from a Resource on the heap, i.e: void func() { Foo* foo = new Foo; foo->reference(); foo->unReference(); // foo destroyed } or void func() { Foo& foo = *new Foo; foo.reference(); foo.unReference(); // foo destroyed however this doesn't stop people from trying to reference an item which appears on the stack if created that way. We came up with the solution of embodying the concept of determining if an object is created on the free store or not in a seperate class and then deriving Resource from it. The reference() member would then check to make sure the object has been created on the free store before doing anything, if it wasn't it would cause a fatal error. class Alloc { public: // ... bool allocatedUsingNew(); }; class Reference : public Alloc { public: // ... void reference() { if (allocatedUsingNew()) myNumRefs++; else { abort(); cerr << "Object not a free standing object on the heap." << endl; } } }; It should be noted that this doesn't stop you from creating instances of Foo on the stack, it just stops you from trying to reference it. Now to consider the point which you originally brought up about arrays of objects on the heap. As you state, overloading operator new() to find out if objects are created on the free store doesn't pick up the case of objects as part of arrays. If it did however, the scheme which I outline above would fail with the same sort of problem as objects being created on the stack. Namely the destructor would be called twice, first when you perform an unReference() and secondly when delete the array of objects. A w orse case actually exists if the array is deleted before an unReference() occurs, as the actual space which the this pointer would be set doesn't exist anymore. Similar problems also arise when considering objects which are members of another class, however I won't go into that here. Finally just to put into perspective why we use this scheme anyway, it is because we have created a class library which is as robust as possible We sacrifice some efficiency in the process, however we would prefer to have the program abort and give some message describing what programming principle you violated as opposed to a straight core dump occuring, with absoulutely no idea what went wrong. Graham Dumpleton (grahamd@otc.otca.oz.au)
jimad@microsoft.UUCP (Jim ADCOCK) (01/12/91)
In article <20083@netcom.UUCP> aed@netcom.UUCP (Andrew Davidson) writes: >It is possible to overload the new and delete operators. I agree. See also "The Annotated C++ Reference Manual," pg 280-284, and/or XJ316 working draft section 12.5 I would expect only very old C++ compilers not to support this feature.