[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: