From: Seungbeom Kim on
On 2010-04-02 00:36, pfultz2 wrote:
>
> This is kind of a rough sketch of what im trying to accomplish. When I
> want to deallocate the array, I need to check if it on the heap
> because it could be pointing to an array on the stack that it got from
> value_array. Now, when I use a garbage collector this is ok, but If
> want to manage the array myself, I guess I will need to add an extra
> bool in there to signal that it is a heap array or a stack array. But
> I would really like to avoid carrying around an extra integer in the
> class., so I figure maybe I could check it when i delete it.

The question to ask is about ownership: who owns the underlying array?
If there is a single owner, the owner who created the object should be
the one who will destroy it, and the owner knows that it created the
object, so no problem. Otherwise, the ownership is shared, and generally
you want to use some reference counting to determine when no owner is
going to remain. It's not about whether the object is on the stack or
on the heap, or whether it is safe to call delete/delete[].

In your example, the class 'array' could either own the array pointed to
by 'data', or not. This is not always the same as whether the object is
on the heap or not: the copy constructor could receive a heap-allocated
array that has another owner, or what happens if you create 'array' with
an integer argument and copy it so there are multiple 'array' objects
with the same value of 'data', and the destructor of the class 'array'
should NOT destroy the array even though it is on the heap, because it
isn't owned by the class 'array'.

Therefore, you should make clear whether the class 'array' owns the
array pointed to by 'data', and it can be done by setting a flag when
its constructor calls new[].

bool owns;
size_t len;
T* data;

explicit array(size_t n) : owns(true), len(n), data(new T[N]) { }
template<size_t N>
array(value_array<T, N>& a) : owns(false), len(N), data(a.pointer()) { }
array(const array& a) : owns(false), len(a.len), data(a.data) { }
~array() { if (owns) delete[] data; }

Or, equivalently:

size_t len;
T* my_own;
T* data;

explicit array(size_t n) : len(n), my_own(new T[N]), data(my_own) { }
template<size_t N>
array(value_array<T, N>& a) : len(N), my_own(0), data(a.pointer()) { }
array(const array& a) : len(a.len), my_own(0), data(a.data) { }
~array() { delete[] my_own; }

However, a bigger problem is that this class 'array' has dual
responsibilities: managing a (potential) ownership and providing a
uniform interface. A cleaner design is to separate the concerns:
you have 'value_array' for a static/automatic array, and you can use
something like boost::scoped_array for a dynamic array, and let the
generic 'array' point either to 'value_array' or boost::scoped_array.
(At this stage I begin to wonder why you need this shallow extra level
of abstraction at all, but anyway...) Then the first two classes
deal with the ownership issue, and 'array' doesn't have to worry.
This also eliminates the need for the destructor of 'array', and
makes it easier to correctly handle the assignment, too.

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Martin B. on
On 03.04.2010 00:03, James Kanze wrote:
> On Apr 1, 3:04 pm, Goran<goran.pu...(a)gmail.com> wrote:
>> On Mar 31, 9:39 pm, pfultz2<pful...(a)yahoo.com> wrote:
>
>> There is NO "neater way" but to KNOW, at any point in your
>> code, what you need to do with any object/variable.
>
> Note that in practice, most types will either be always
> allocated dynamically, or never allocated dynamically. There
> are exceptions, but they aren't that frequent.
>

You got that the wrong way round. In therory most types in a given prg
environment should be of the kind to either be used dynamically or not.
In *practice* it will be a muble jumble of different styles and weird
constructs.
// My favourite I-have-been-a-Java-programmer snippet:
{
Obj* o = new Obj(...);
...
o->foo();
...
if(o) delete o; // yes, I know, the if is useless
}

Of course, I don't think that's a reason to require any function that
determines where a pointer belongs.

cheers,
Martin

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: George Neuner on
On Fri, 2 Apr 2010 10:02:38 CST, Mark Zaytsev
<mark.zaytsev(a)gmail.com> wrote:

>On Apr 1, 10:03 am, George Neuner <gneun...(a)comcast.net> wrote:
>> On Wed, 31 Mar 2010 13:39:59 CST, pfultz2 <pful...(a)yahoo.com> wrote:
>> >I want detect if a pointer is pointing to memory on the heap or the
>> >stack, so I came up with this approach:
>
>[skip]
>
>>
>> The stack check works on Unix/Linux and Windows because their stacks
>> are contiguous - but there may be other platforms for which it won't
>> work (although I've yet to meet such a platform).
>>
>
>Stack of which thread ?
>If object allocated on the other thread's stack, your check will say:
>HEAP...

Not exactly.

The Windows heap check will only return true if the address actually
is in on the heap somewhere. However, you do raise a good point about
the possibility of multiple thread stacks.

When you create a thread with default stack, Windows allocates the
stack block separately from the program's heap(s) ... but it is
possible to force a thread to use a heap allocated block as stack. In
that case, the heap check would say the object is in the heap.

You can enumerate the threads in your process (see the docs for
CreateToolhelp32Snapshot or equivalent in 64-bit land), find their
stacks and examine them in a manner similar to the heap walk, but it
is dangerous because you are invoking system debugging tools to
reflect on your own program. I've never tried most of the things
ToolHelp can supposedly do.

George

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: James Kanze on
On Apr 3, 9:35 pm, "Martin B." <0xCDCDC...(a)gmx.at> wrote:
> On 03.04.2010 00:03, James Kanze wrote:

> > On Apr 1, 3:04 pm, Goran<goran.pu...(a)gmail.com> wrote:
> >> On Mar 31, 9:39 pm, pfultz2<pful...(a)yahoo.com> wrote:

> >> There is NO "neater way" but to KNOW, at any point in your
> >> code, what you need to do with any object/variable.

> > Note that in practice, most types will either be always
> > allocated dynamically, or never allocated dynamically.
> > There are exceptions, but they aren't that frequent.

> You got that the wrong way round. In therory most types in a
> given prg environment should be of the kind to either be used
> dynamically or not. In *practice* it will be a muble jumble
> of different styles and weird constructs.

:-).

That depends entirely on the quality of code review.
Although...

> // My favourite I-have-been-a-Java-programmer snippet:

Java has corrupted quite a few C++ programmers. And vice versa.
IMHO, it was a big mistake for Java to adopt a syntax so similar
to C++'s, while defining a language in which the appropriate
solutions for so many problems are so different. I does lead to
confusion.

--
James Kanze

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nevin :-] Liber on
In article
<3ae2c4c0-ae42-40c9-b768-cadf69f3e9a6(a)z39g2000vbb.googlegroups.com>,
pfultz2 <pfultz2(a)yahoo.com> wrote:

> I want detect if a pointer is pointing to memory on the heap or the
> stack, so I came up with this approach:
>
> bool isOnHeap(void * p)
> {
> int i = 0;
> int * s = &i;
> return (p > s);
> }
>
> I dont if this is the best or most portable way to do it. And im not
> sure how well it works for static and global variables, do they start
> on the end of memory? or at the begining? The reason why i want to do
> this is need to delete pointers sometimes, and some of them point to
> memory on the stack, so therefore i dont want to delete them,

Detecting if an object is in the heap is not a sufficient test to see if
you need to manage its lifetime.

For example:

struct BufferManager
{
explicit BufferManager(char* b) : buffer(b) {}
~BufferManager() { if InHeap(buffer) delete buffer; }

char* buffer;
};

struct Wrapper
{
Wrapper() : mb(buf) {}

char buf[100];
BufferManager bm;
};

int main()
{
char stackBuf[100];
BufferManager stackBM(stackBuf);
BufferManager heapBM(new char[100]);
Wrapper stackWrapper;
std::auto_ptr<Wrapper> heapWrapper(new Wrapper);
}

When heapWrapper is destructed, it will incorrectly call delete on
heapWrapper->buf because heapWrapper->buf is in the heap but
heapWrapper->bm should not be managing its lifetime.

--
Nevin ":-)" Liber <mailto:nevin(a)eviloverlord.com> 773 961-1620

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]