delete Vs. delete []

F

fermisoft

I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}


During the program execution pointers of different types are typecasted
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

Memory deallocation happens in the destructor of CMsg by invoking
delete. This deallocation works only for deleting a single block of
memory. So, while trying to delete memory assosiated with pointer to
array, exception is thrown.

How to identify pointer to an array? and deallocate accordingly by
calling delete [] ?
 
A

Alf P. Steinbach

* (e-mail address removed):
I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}


During the program execution pointers of different types are typecasted
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

Memory deallocation happens in the destructor of CMsg by invoking
delete. This deallocation works only for deleting a single block of
memory. So, while trying to delete memory assosiated with pointer to
array, exception is thrown.

How to identify pointer to an array? and deallocate accordingly by
calling delete [] ?

The best strategy is to use

std::string m_body;

or

std::vector<char> m_body;

if the array of chars must be contigous, e.g. for interfacing to C.

If that doesn't help you, you must probably just to keep track, in an
extra member variable, of what m_body currently is.
 
B

benben

I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}


During the program execution pointers of different types are typecasted
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

Memory deallocation happens in the destructor of CMsg by invoking
delete. This deallocation works only for deleting a single block of
memory. So, while trying to delete memory assosiated with pointer to
array, exception is thrown.

How to identify pointer to an array? and deallocate accordingly by
calling delete [] ?

class CMsg
{
public:
bool is_array;
void* m_body;

~CMsg()
{
if (is_array) delete[] m_body;
else delete m_body;
}
};

Regards,
Ben
 
T

Tomás

benben posted:
I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body; } }


During the program execution pointers of different types are typecasted
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

Memory deallocation happens in the destructor of CMsg by invoking
delete. This deallocation works only for deleting a single block of
memory. So, while trying to delete memory assosiated with pointer to
array, exception is thrown.

How to identify pointer to an array? and deallocate accordingly by
calling delete [] ?

class CMsg
{
public:
bool is_array;
void* m_body;

~CMsg()
{
if (is_array) delete[] m_body;
else delete m_body;
}
};

Regards,
Ben

Do you not have to give "delete" the correct type? For instance, if you
declared an "int" with "new", then "delete" wasn't an argument of type
"int*", rather than a "void*"?


-Tomás
 
D

Dietmar Kuehl

benben said:
class CMsg
{
public:
bool is_array;
void* m_body;

~CMsg()
{
if (is_array) delete[] m_body;
else delete m_body;
}
};

Note that the above code is causing undefined behavior according
to the C++ standard: you cannot delete an object through a pointer
of type 'void'. The reasoning for this is quite simple: you can
only delete an object through a pointer with a different type than
the object if the static type of the pointer has a virtual
destructor. This does not apply to 'void'. If the static type of
the pointer has no virtual destructor, the type dynamic type of
the object being deleted has to be identical to the static type.
Since you cannot allocate an object of type 'void', using 'delete'
with a 'void' pointer is always illegal. The standard even has a
note spelling this out (see 5.3.5, expr.delete, paragraph 3).

For array objects the situation is even simpler: the static type
of the array object has to match the dynamic type of the array
object. Period.
 
D

Dietmar Kuehl

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}

You cannot delete an object using a pointer to 'void'. Period. For
more details see my reply to "benben" in this thread. If you really
need to do something like this, you should consider using
'shared_ptr' (either from Boost or from TR1) and use it with an
appropriate deleter object.
 
H

Heinz Ozwirk

I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}


During the program execution pointers of different types are typecasted
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

Memory deallocation happens in the destructor of CMsg by invoking
delete. This deallocation works only for deleting a single block of
memory. So, while trying to delete memory assosiated with pointer to
array, exception is thrown.

How to identify pointer to an array? and deallocate accordingly by
calling delete [] ?

You know how it has been allocated, so just remember it. And also remember
the type that has been allocated. You cannot safely allocate an object (or
an array of object) of one type and then delete it using a pointer to some
other type (including void). Before you can safely delete any memory, you
have to cast the pointer back to the original type.

An second thought, leave it to your CMsg class to allocate memory. You can
specify the number of elements in the constructor (or some other method to
allocate memory) and internally always allocate an array of elements, even
if it only has one element.

Also, you could make CMsg a template class or you could use different
derived classes for different types of messages.

If you want to (or have to) stick to your raw memory, use malloc and free.
At least then you will always see clearly that you do something nasty.

Regards
Heinz
 
B

benben

Do you not have to give "delete" the correct type? For instance, if you
declared an "int" with "new", then "delete" wasn't an argument of type
"int*", rather than a "void*"?

True, my apologies!

My point is use another flag to make a decision on whether to use delete
or delete[].
 
P

Pete Becker

I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}

If your code is trafficking in void*s you should be using malloc and free.
 
A

Artie Gold

I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}


During the program execution pointers of different types are typecasted
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

Memory deallocation happens in the destructor of CMsg by invoking
delete. This deallocation works only for deleting a single block of
memory. So, while trying to delete memory assosiated with pointer to
array, exception is thrown.

How to identify pointer to an array? and deallocate accordingly by
calling delete [] ?
As a high school classmate of mine[1] used to say looking at a listing
of (typically failing) code: "Bad Karma."

There's no way to know; you have a design problem. Most likely the
situation is that the class doesn't handle itself very well. The member
`m_body' needs to be allocated with code from the class; only then can
you control deallocation.

More significant is the fact that it seems likely that the class you
give as an example doesn't *do* enough. Too much program logic that is
primarily germane to a given object lies outside its class code.

Anything more would be venturing too far afield for this forum.

HTH,
--ag

[1] a real person
 
B

Ben Pope

I have a strange problem in my project.

I have a class like this......

class CMsg
{
public:
void *m_body;

~CMsg()
{
delete m_body;
}
}


During the program execution pointers of different types are typecasted

Why are they typecasted?
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

That's horrible. In the case of 1 or more of something, don't
distinguish between the 1 and the "more". An array of 1 is perfectly
acceptable.
Memory deallocation happens in the destructor of CMsg by invoking
delete. This deallocation works only for deleting a single block of
memory. So, while trying to delete memory assosiated with pointer to
array, exception is thrown.

The problem is that the entity allocating is not the entity
deallocating. What you need, is a class that deals with those issues;
specifically an RAII class that allocates in it's constructor, and
deallocates in it's destructor. You can have a single element holder,
and an array holder; when they go out of scope, (if they are allocated
on the free store, deleted), then they can successfully delete or
delete[] their contents.

These classes are implemented in the shape of smart pointers. Boost has
a shared_ptr for the first case, and some equivalent for arrays in the
latter case (shared_array, or scoped_array). You can also use a
shared_ptr in the second case, if you provide the correct deallocator to it.
How to identify pointer to an array? and deallocate accordingly by
calling delete [] ?

Push the delete requirement into the class doing the allocation. This
is often easier of you also move the allocation as well, and have a
class specifically for allocation and deallocation. (smart pointer).

Ben Pope
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

During the program execution pointers of different types are typecasted
and assigned to m_body. Some pointers meant for a single block (p= new
char) and few are pointers to array. (Memory was allocated by p = new
char[nSize]).

A simple solution is to always use [ ], when you want to allocate a single
char just use p= new char [1];
 
F

fermisoft

Thanks Dietmar!!!!! I got a picture of new/delete. Now can you clear my
small doubt??? Look out the code........
{
Struct_t *ptr = (Struct_t *) new char[l_size];

...........
..........

// Here I need to deallocate the memory.

char *temp_ptr = (char *) ptr;
delete [] temp_ptr;
}

Am I right in the above deallocation??
 
D

Dietmar Kuehl

Thanks Dietmar!!!!! I got a picture of new/delete. Now can you clear my
small doubt??? Look out the code........
{
Struct_t *ptr = (Struct_t *) new char[l_size];

The above cast causes the result to be implementation defined. From
a standard perspective, everything following is essentially not
strictly specified. Use

Struct_t* ptr = new Struct_t;

and you are fine. In any case, you need to construct the object. If
you really want to allocate memory differently, use the proper
variant of 'operator new()' or 'malloc()' and don't forget to
construct the object:

void* mem = operator new(sizeof(Struct_t));
Struct_t* ptr = new(mem) Struct_t;

Of course, every constructed object needs destruction and using a
variation of placement new (except for the 'std::nothrow' variant)
requires the use of manual destruction and memory release:

ptr->~Struct_t();
operator delete(mem);
// Here I need to deallocate the memory.

char *temp_ptr = (char *) ptr;
delete [] temp_ptr;
}

Am I right in the above deallocation??

You wander implementation defined lands. Maybe that works, maybe
it doesn't. You would have to haunt down the documentation of your
C++ implementation to figure out what is supposed to be going on.

Don't even think about playing tricks if you don't know precisely
what you are doing! From your questions it is clear that you don't
know what you are doing, i.e. don't do it! I strongly doubt that
you need to do anything like what you have done. Maybe you would
be better off telling us what you actually want to do instead of
asking details about an almost certainly crippled "solution".
 
T

Tomás

posted:
Thanks Dietmar!!!!! I got a picture of new/delete. Now can you clear my
small doubt??? Look out the code........
{
Struct_t *ptr = (Struct_t *) new char[l_size];

It's bad to use those style casts now. They've been replaced by:

const_cast
static_cast
dynamic_cast
reinterpret_cast

Struct_t* ptr = reinterpret_cast<Struct_t*>( new char[l_size] );

...........
..........

// Here I need to deallocate the memory.

char *temp_ptr = (char *) ptr;


delete [] temp_ptr;
}

Am I right in the above deallocation??

It looks okay.

There's no need for the temp pointer though:

delete [] reinterpret_cast<char*>(ptr);


-Tomás
 
T

Tomás

Dietmar Kuehl posted:
Thanks Dietmar!!!!! I got a picture of new/delete. Now can you clear my
small doubt??? Look out the code........
{
Struct_t *ptr = (Struct_t *) new char[l_size];

The above cast causes the result to be implementation defined. From
a standard perspective, everything following is essentially not
strictly specified. Use

Struct_t* ptr = new Struct_t;

and you are fine.


I think all is fine and dandy if "Struct_t" is a POD. You're allowed play
with any POD's memory as if it were an array of "char"'s, like:

char mem_storage[sizeof(Struct_t)];

Struct_t* ptr = new(mem_storage) Struct_t;

-Tomás
 
P

peter koch

Tomás said:
Dietmar Kuehl posted:
Thanks Dietmar!!!!! I got a picture of new/delete. Now can you clear my
small doubt??? Look out the code........
{
Struct_t *ptr = (Struct_t *) new char[l_size];

The above cast causes the result to be implementation defined. From
a standard perspective, everything following is essentially not
strictly specified. Use

Struct_t* ptr = new Struct_t;

and you are fine.


I think all is fine and dandy if "Struct_t" is a POD. You're allowed play
with any POD's memory as if it were an array of "char"'s, like:

char mem_storage[sizeof(Struct_t)];

Struct_t* ptr = new(mem_storage) Struct_t;

-Tomás

Nope - there are alignment problems. You thus have to use malloc.

/Peter
 
D

Dietmar Kuehl

Tomás said:
Dietmar Kuehl posted:
Thanks Dietmar!!!!! I got a picture of new/delete. Now can you clear my
small doubt??? Look out the code........
{
Struct_t *ptr = (Struct_t *) new char[l_size];
I think all is fine and dandy if "Struct_t" is a POD. You're allowed play
with any POD's memory as if it were an array of "char"'s, like:

char mem_storage[sizeof(Struct_t)];

Struct_t* ptr = new(mem_storage) Struct_t;

Do you have any quote from the standard backing you up on this? In
particular, I would assume that there could be different alignment
restrictions. For example, assume this POD:

struct Struct_t { double value; };

The alignment requirement for this POD could be an address dividable
by eight. A 'char' array with eight chars can easily be aligned to
every address although it might normally be aligned to addresses
dividable by four.

Since I haven't seen any good reason yet to do differently, what is
wrong with using the low-level memory allocation routines ('malloc()',
'operator new()', etc.) instead of 'new char[...]'? I seriously doubt
that the original author actually really needs to work with untyped
objects. I have had needs to work with odd objects in the past but
these were solely when implementing certain container data structures.
 
T

Tomás

Nope - there are alignment problems. You thus have to use malloc.


So does "malloc" allocate memory at such an address that will satisfy
_any_ type?


-Tomás
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top