Topic: Check whether object has been allocated on heap


Author: JdeBP@jba.co.uk (Jonathan de Boyne Pollard)
Date: 1996/04/24
Raw View
Fergus Henderson (fjh@mundook.cs.mu.OZ.AU) wrote:
| JdeBP@jba.co.uk (Jonathan de Boyne Pollard) writes:
|
| >Felix I. Wyss (fwyss@linx.co.uk) wrote:
| >| If not, what's about a function "is_dynamic(x)" (where 'x' is a pointer to
| >| an object) that returns 1 for dynamically allocated objects and 0 in all
| >| other cases.
| >
| >And how do you expect an implementation to be able to tell ?
|
| There's no portable way to do it, of course, but an implementation
| could do it by knowing which part of the address space contains the heap.

There's no guarantee that the implementation knows which part of the
address space contains the heap, or that it can find out, either.

Consider a program that overrides the global operators new and delete.  It
calls an external function to allocate some address space (e.g. an
operating system API function) and uses that address space for the heap.

There's nothing ill-formed about such a program as far as I can see.  Yet
the C++ implementation cannot possibly determine that the address space that
the replacement operators new and delete are using as their heap is heap
memory, and so the implementation cannot possibly implement
is_dynamic(void*) in such a way that is_dynamic(new char) returns true.

| I think that's a red herring.  If your replacement operators new
| and delete call malloc() and free(), then the memory they allocated
| will be allocated on the heap.  If they allocate from a statically
| allocated array, then they're not strictly conforming anyway (because
| there's no way to ensure correct alignment), but the memory doesn't
| come from the heap, and so I think it would be satisfactory for
| is_dynamic() to return false on such addresses.  If they allocate
| it any other way (e.g. using mmap()), then they're not conforming,
| so all bets are off.

Erm ... Fergus.  We don't have "conforming" and "strictly conforming" in
Standard C++.  We have "well-formed" and "ill-formed".  Have you been doing
too much reading of the ISO C standard ?  (-:

Niggles aside, there's no syntax rule or diagnosable semantic rule in the
WP that I can find that is violated by a program that calls an operating
system API function (as long as the O/S API has C language or C++ language
bindings).  Why do you think that such programs are ill-formed ?

Or is it the fact that you have to pass an address to mmap() that is
upsetting you ?  In which case, how do you feel about a program that calls
sbrk(), DosAllocMem(), GlobalAlloc() or whatever to obtain its heap ?

Unless we can find a violation of a syntax rule or of a diagnosable
semantic rule that makes such programs ill-formed, we find ourselves with
the possibility of well-formed programs being able to implement replacement
operators new and delete in such a way that the implementation cannot
possibly determine whether or not a given address is the address of an
object allocated via `new'.


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: JdeBP@jba.co.uk (Jonathan de Boyne Pollard)
Date: 1996/04/25
Raw View
Wolfgang Reddig (wolfgang@CS.Bonn.EDU) wrote:
| But the fact that an object is allocated on the heap does not qualify it
| to call delete on it, since the object might be an embedded object
| (non pointer data member) or an element of an array - and only the enclosing
| object or the array are allocated via 'new'.
|
| Some might consider passing a pointer to an embedded subobject bad
| programming practice - at least with arrays, it happens anyway.

Of course since the implementation knows how it keeps house in its own heap,
it can easily determine whether a given pointer in its heap points the
start of a complete object or not.  Most heap implementations use
variations on the linked list approach, and so should be able to determine
whether a pointer was a pointer to a complete object or not simply by using
the brute force approach of iterating over the linked list of allocated
complete objects and comparing their addresses with the pointer supplied.

But this is an aside.  The main reason that I was posting was that I forgot
to mention in my last article that all of the problems mentioned in my last
article to do with user-supplied dynamic storage allocation functions would
go away were the constraint imposed that either _both_ ::operator new and
is_dynamic(void *) are replaced, or _neither_ are.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Barry Margolin <barmar@tools.bbnplanet.com>
Date: 1996/04/25
Raw View
In article <4lhqtq$o1r@mulga.cs.mu.oz.au>,
Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote:
>I think that's a red herring.  If your replacement operators new
>and delete call malloc() and free(), then the memory they allocated
>will be allocated on the heap.  If they allocate from a statically
>allocated array, then they're not strictly conforming anyway (because
>there's no way to ensure correct alignment), but the memory doesn't
>come from the heap, and so I think it would be satisfactory for
>is_dynamic() to return false on such addresses.

You said that the purpose of is_dynamic() is to determine whether you're
expected to delete the object.  If it returns false in the case of some
replacement "new" operators, it doesn't serve that purpose, and you'll have
memory leaks as a result.  I suppose it's better to fail in this way than
to have false positives (trying to delete non-heap objects can have
disastrous results), but I think users would expect a function like this to
be completely reliable.  You might be able to get away with your definition
if you renamed it safe_to_delete() (true means it's definitely safe, false
means it's not safe or it's unknown).
--
Barry Margolin
BBN PlaNET Corporation, Cambridge, MA
barmar@bbnplanet.com
Phone (617) 873-3126 - Fax (617) 873-6351


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1996/04/26
Raw View
JdeBP@jba.co.uk (Jonathan de Boyne Pollard) writes:

>Fergus Henderson (fjh@mundook.cs.mu.OZ.AU) wrote:
>| JdeBP@jba.co.uk (Jonathan de Boyne Pollard) writes:
>|
>| >Felix I. Wyss (fwyss@linx.co.uk) wrote:
>| >| If not, what's about a function "is_dynamic(x)" (where 'x' is a pointer to
>| >| an object) that returns 1 for dynamically allocated objects and 0 in all
>| >| other cases.
>| >
>| >And how do you expect an implementation to be able to tell ?
>|
>| There's no portable way to do it, of course, but an implementation
>| could do it by knowing which part of the address space contains the heap.
>
>There's no guarantee that the implementation knows which part of the
>address space contains the heap, or that it can find out, either.

What do you mean by "the heap"?  The implementation could *define*
which part of the address space is the heap.

>Consider a program that overrides the global operators new and delete.  It
>calls an external function to allocate some address space (e.g. an
>operating system API function) and uses that address space for the heap.
>
>There's nothing ill-formed about such a program as far as I can see.

No, but its behaviour is not defined by the C++ standard.

>| If they allocate
>| it any other way (e.g. using mmap()), then they're not conforming,
>| so all bets are off.
>
>Erm ... Fergus.  We don't have "conforming" and "strictly conforming" in
>Standard C++.  We have "well-formed" and "ill-formed".  Have you been doing
>too much reading of the ISO C standard ?  (-:

Yes, I should have said "they have undefined behaviour" rather than
"they're not conforming".  But my statement that "all bets are off"
still holds.

In any case, implementations can know where global/static data is stored
and where the stack is stored, and can assume that any other
storage qualifies as being "dynamic".

(Certainly there are some implementations for which knowing where
all global/static data is stored is not trivial.  So I'm not
suggesting that it is necessarily easy.  But it should be possible.)

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1996/04/27
Raw View
Barry Margolin <barmar@tools.bbnplanet.com> writes:

| Fergus Henderson <fjh@mundook.cs.mu.OZ.AU> wrote:
| >I think that's a red herring.  If your replacement operators new
| >and delete call malloc() and free(), then the memory they allocated
| >will be allocated on the heap.  If they allocate from a statically
| >allocated array, then they're not strictly conforming anyway (because
| >there's no way to ensure correct alignment), but the memory doesn't
| >come from the heap, and so I think it would be satisfactory for
| >is_dynamic() to return false on such addresses.
|
| You said that the purpose of is_dynamic() is to determine whether you're
| expected to delete the object.

I didn't say that, although some previous poster in this thread may have done.

I was just disagreeing with a claim that implementations could not figure
out whether a particular address was from the heap or not.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: JdeBP@jba.co.uk (Jonathan de Boyne Pollard)
Date: 1996/04/22
Raw View
Felix I. Wyss (fwyss@linx.co.uk) wrote:
| If not, what's about a function "is_dynamic(x)" (where 'x' is a pointer to
| an object) that returns 1 for dynamically allocated objects and 0 in all
| other cases.

And how do you expect an implementation to be able to tell ?

Think carefully before you answer.  Remember that you are allowed to
replace operators new and delete.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1996/04/23
Raw View
JdeBP@jba.co.uk (Jonathan de Boyne Pollard) writes:

>Felix I. Wyss (fwyss@linx.co.uk) wrote:
>| If not, what's about a function "is_dynamic(x)" (where 'x' is a pointer to
>| an object) that returns 1 for dynamically allocated objects and 0 in all
>| other cases.
>
>And how do you expect an implementation to be able to tell ?

There's no portable way to do it, of course, but an implementation
could do it by knowing which part of the address space contains the heap.

>Think carefully before you answer.  Remember that you are allowed to
>replace operators new and delete.

I think that's a red herring.  If your replacement operators new
and delete call malloc() and free(), then the memory they allocated
will be allocated on the heap.  If they allocate from a statically
allocated array, then they're not strictly conforming anyway (because
there's no way to ensure correct alignment), but the memory doesn't
come from the heap, and so I think it would be satisfactory for
is_dynamic() to return false on such addresses.  If they allocate
it any other way (e.g. using mmap()), then they're not conforming,
so all bets are off.

All that is not to say whether an is_dynamic() function is a good or
bad thing, but just to say that it can be easily implemented on most
(though not all) architectures.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Bradd W. Szonye" <bradds@ix.netcom.com>
Date: 1996/04/23
Raw View
On Friday, April 19, 1996, "Felix I. Wyss" wrote...
> Hello folks!
>
> I'm sure this question has been asked many times but here is it anyway:
>
> How can I determine whether an object has been instantiated by
allocating
> heap space ("new") or whether it is global/static/automatic or even a
member
> of an other object.
> In other words: does a particular object have to be destroyed by calling
> "delete" or not.
> Is there a proper (and portable) way to do determine that or is there a
> proposal for the new C++ standard to achieve this functionality?
> If not, what's about a function "is_dynamic(x)" (where 'x' is a pointer
to
> an object) that returns 1 for dynamically allocated objects and 0 in all
> other cases.
>
> I often came across situations where this information would have been
very
> useful.
>
> Thank you for your attention!
>
> Felix (fwyss@linx.co.uk)

The answer to your question is highly-system dependent. It's the sort of
thing you could figure out how to do for your specific compiler (in its
current version), but it wouldn't be portable, possibly not even to the
next version. Maybe. For COFF-compatible executables, like under Windows
NT/95 and a lot of Unix systems, you might be able to get the information
you need from the COFF/PE header. I won't go into deep details, but here's
the basic idea:

(1) Data lives in one of three places, the static allocation area, the
stack, and the heap. You want stuff on the heap.
(2) The COFF header tells you where the static initialization areas are
supposed to be.
(3) The COFF header tells you where the stac is supposed to be.
(4) Everything else is probably on the heap.

To find out about the COFF header, which is large and somewhat
complicated, bug some Microsoft or Unix systems people.
--
Bradd W. Szonye (bradds@ix.netcom.com), Doubleplus Corporation

"To chill or to pop a cap in my dome, whoomp, there it is."
   -- Hamlet, Prince of Denmark



[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: wolfgang@CS.Bonn.EDU (Wolfgang Reddig)
Date: 1996/04/23
Raw View
In article <01bb310f.ac068700$38c2b7c7@Zany.localhost>, "Bradd W. Szonye" <bradds@ix.netcom.com> writes:
>
>On Friday, April 19, 1996, "Felix I. Wyss" wrote...
>> Hello folks!
>>
>> I'm sure this question has been asked many times but here is it anyway:
>>
>> How can I determine whether an object has been instantiated by
>allocating
>> heap space ("new") or whether it is global/static/automatic or even a
>member
>> of an other object.
>> In other words: does a particular object have to be destroyed by calling
>> "delete" or not.
>> Is there a proper (and portable) way to do determine that or is there a
>> proposal for the new C++ standard to achieve this functionality?
>> If not, what's about a function "is_dynamic(x)" (where 'x' is a pointer
>to
>> an object) that returns 1 for dynamically allocated objects and 0 in all
>> other cases.
>>
>> I often came across situations where this information would have been
>very
>> useful.
>>
>> Thank you for your attention!
>>
>> Felix (fwyss@linx.co.uk)
>
>The answer to your question is highly-system dependent. It's the sort of
>thing you could figure out how to do for your specific compiler (in its
>current version), but it wouldn't be portable, possibly not even to the
>next version. Maybe. For COFF-compatible executables, like under Windows
>NT/95 and a lot of Unix systems, you might be able to get the information
>you need from the COFF/PE header. I won't go into deep details, but here's
>the basic idea:
>
>(1) Data lives in one of three places, the static allocation area, the
>stack, and the heap. You want stuff on the heap.
>(2) The COFF header tells you where the static initialization areas are
>supposed to be.
>(3) The COFF header tells you where the stac is supposed to be.
>(4) Everything else is probably on the heap.
>
>To find out about the COFF header, which is large and somewhat
>complicated, bug some Microsoft or Unix systems people.
>--
>Bradd W. Szonye (bradds@ix.netcom.com), Doubleplus Corporation

But the fact that an object is allocated on the heap does not qualify it
to call delete on it, since the object might be an embedded object
(non pointer data member) or an element of an array - and only the enclosing
object or the array are allocated via 'new'.

Some might consider passing a pointer to an embedded subobject bad programming
practice - at least with arrays, it happens anyway.

Regards,
Wolfgang

[ moderator's note: As I mentioned in another article, Scott Meyers'
  new book "More Effective C++" contains a detailed analysis of this
  subject. -sdc
]



[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Felix I. Wyss" <fwyss@linx.co.uk>
Date: 1996/04/19
Raw View
Hello folks!

I'm sure this question has been asked many times but here is it anyway:

How can I determine whether an object has been instantiated by allocating
heap space ("new") or whether it is global/static/automatic or even a member
of an other object.
In other words: does a particular object have to be destroyed by calling
"delete" or not.
Is there a proper (and portable) way to do determine that or is there a
proposal for the new C++ standard to achieve this functionality?
If not, what's about a function "is_dynamic(x)" (where 'x' is a pointer to
an object) that returns 1 for dynamically allocated objects and 0 in all
other cases.

I often came across situations where this information would have been very
useful.

Thank you for your attention!

Felix (fwyss@linx.co.uk)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]