Re: [OT] C++ question re. dyn. mem.
I think all of the responses are missing something very
important. Let me try....
On Sunday 03 August 2003 08:57 pm, MJM wrote:
> Will the free store be properly maintained when the following
> is executed? // a simple object is defined
> typedef struct
> {
> uint32_t a;
> uint64_t b;
> uint8_t c;
> } t_my_type;
OK so far. It's more elegant to say:
struct t_my_type;
{
uint32_t a;
uint64_t b;
uint8_t c;
};
but I won't dwell on that.
It is not clear what uint32_t, uint64_t, and uint8_t are. Let
me assume that they are names of classes.
> // allocate some memory for an instance of this object
> t_my_type * p_a = (t_my_type) new t_my_type;
You left out the "*" in the cast. I assume this is a typo.
Actually, the cast isn't necessary. The C++ "new" is not just
another name for malloc. It gets memory using malloc, then
invokes a constructor to initialize it. This difference is
important. The cast isn't necessary because it already is the
correct type.
> // change the way it is accessed to prove a point
> int * p_b = (int *) p_a;
> // p_a and p_b point to the same block of dyn. allocated
> memory;
Hopefully. In this case, probably, but it cannot be guaranteed
to be true in general. When you use multiple inheritance, it
will probably not be true.
> // return the memory to free storage using the second
> // pointer
> delete p_b;
Delete is not the same as free. It first invokes the
destructor, then returns the space using free. Since you
changed the type of the pointer, you get a different
destructor.
Since you didn't define a destructor, by default it just calls
the destructors for all the members.
> I think the free store will be maintained properly because
> there is a control block attached to the allocated block of
> storage that defines the length of the allocated memory.
For this specific example, probably, but you can't count on it
in general.
Since you didn't say what uint64_t is, let me make a diabolical
definition of it.
class uint64_t
{
long* x;
uint64_t() {x = new long;}
~uint64_t() {delete x;}
};
Now, when I do:
t_my_type * p_a = new t_my_type;
I actually get the struct, but since uint64_t has a constructor
it is initialized. In this case, the initialization uses "new"
to get even more memory. So, you actually have 2 blocks of
memory.
If I do:
delete p_a;
the destructors will be called, deleting the hidden memory
block, then the real one gets freed.
If I do:
int * p_b = (int *) p_a;
delete p_b;
It doesn't call the destructors, so the internally allocated
piece is still allocated, and no longer accessable. It's a
leak.
Actually, you get the destructor for int, whatever that is.
Reply to: