C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

new/delete for different POD types?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Ralf Fassel
Guest





PostPosted: Wed May 17, 2006 10:21 am    Post subject: new/delete for different POD types? Reply with quote



Consider:

void *foo = new int[10];
...
delete [] reinterpret_cast<char*>(foo);

Is this 'allowed' for POD types?
All of my senses say 'no', but...

R'

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Tomás
Guest





PostPosted: Wed May 17, 2006 3:21 pm    Post subject: Re: new/delete for different POD types? Reply with quote



Ralf Fassel posted:

Quote:
Consider:

void *foo = new int[10];
...
delete [] reinterpret_cast<char*>(foo);


You must give delete an expression of the EXACT same type which new
returned (unless of course your writing a program to demonstrate
undefined behaviour).


/* 1 */

int * const p = new int[50];

delete [] p;



/* 2 */

int (&p)[50] =

*reinterpret_cast< int (*)[50] > (

new int[50];

)


delete [] reinterpret_cast< int* >(&p);



/* 3 */

My personal favourite:


int (&array)[50] = *new int[50][0];

delete [] &array;



-Tomás

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





PostPosted: Wed May 17, 2006 3:21 pm    Post subject: Re: new/delete for different POD types? Reply with quote



Ralf Fassel wrote:
Quote:
Consider:

void *foo = new int[10];
...
delete [] reinterpret_cast<char*>(foo);

Is this 'allowed' for POD types?
All of my senses say 'no', but...

The standard says that you can only use the pointer obtained from
a 'reinterpret_cast' to convert it back to the originating pointer type.
The behaviour of any other use is undefined.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask



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





PostPosted: Wed May 17, 2006 3:21 pm    Post subject: Re: new/delete for different POD types? Reply with quote

Ralf Fassel <ralfixx (AT) gmx (DOT) de> wrote:
Quote:
void *foo = new int[10];
...
delete [] reinterpret_cast<char*>(foo);

Is this 'allowed' for POD types?

it's undefined behaviour. Static type of deleted object must be equal to
its dynamic type, OR dynamic type of deleted object must be inherited
from static type AND static type has to have virtual destructor.
However, following is "valid" (but still dubious)

void *foo = new int[10];
// ...
delete [] reinterpret_cast<int*>(foo); // note int*

You may also encapsulate delete expression in a function (or function
template specialisation) and pass pointer to that functions alongside
void * . Obviously, this is very risky, but proper encapsulation may
mitigate some risks.


B.


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





PostPosted: Wed May 17, 2006 10:21 pm    Post subject: Re: new/delete for different POD types? Reply with quote

Tomás wrote:
Quote:
My personal favourite:
int (&array)[50] = *new int[50][0];

interesting indeed, but I suppose that you meant:
int (&array)[50] = *new int[1][50];


B.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Tomás
Guest





PostPosted: Thu May 18, 2006 2:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Bronek Kozicki posted:

Quote:
Tomás wrote:
My personal favourite:
int (&array)[50] = *new int[50][0];

interesting indeed, but I suppose that you meant:
int (&array)[50] = *new int[1][50];


Just realised my mistake now... never occurred to me because I had never
tried to compile it.

I tend to prefer references when dealing with "new":


std::string &str = *new std::string("Hello!");

delete &str;


As for using a reference to an array: I only dynamically allocate memory
when I have to -- and here's two reasons why I'd have to:

A) I don't know how many objects I need until runtime.
B) It's just too big to put on the stack.

If it's A, then I can't use a reference to an array (because I don't
know
its length).

If it's B... well... I've never come across such a situation, which is
why I've been writing:

*new int[50][0]

on newsgroups for a while now and been getting away with it.

Here's some code that just froze my PC for the last ten minutes:


#define NUMELEM(array) ( sizeof(array) / sizeof(*array) )

enum { buf_size = 999999999U /* Nearly a gigabyte */ };

int main()
{
unsigned char (&buffer)[ buf_size ] =
*new unsigned char[1][ sizeof(buffer) ];

const unsigned char* const p_last =
buffer + NUMELEM(buffer) - 1;

unsigned long i = 0;

for ( unsigned char* p = buffer; p != p_last; *p++ = i++ );

delete [] &buffer;
}


-Tomás


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





PostPosted: Thu May 18, 2006 2:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Bronek Kozicki wrote:

<snip>

Quote:
However, following is "valid" (but still dubious)

void *foo = new int[10];
// ...
delete [] reinterpret_cast<int*>(foo); // note int*


OK, I'll bite: why is this "dubious"?

Once you've cast it to a void *, I don't know how
else you'd delete it.

Is static_cast<> legal here?

I'll agree that good programmers try to avoid having to
write stuff like this, if they can.

-- Alan McKenney

<line eater fodder>


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





PostPosted: Thu May 18, 2006 1:21 pm    Post subject: Re: new/delete for different POD types? Reply with quote

In article <sKNag.9302$j7.305865 (AT) news (DOT) indigo.ie>, Tomás
<No.Email (AT) Address (DOT) invalid> writes
Quote:
As for using a reference to an array: I only dynamically allocate
memory
when I have to -- and here's two reasons why I'd have to:

A) I don't know how many objects I need until runtime.
B) It's just too big to put on the stack.

And in both those cases std::vector meets your needs at least 99% of the
time (without loss of efficiency)


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/
youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Martin Vejnár
Guest





PostPosted: Fri May 19, 2006 10:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Tomás wrote:
Quote:
Bronek Kozicki posted:
interesting indeed, but I suppose that you meant:
int (&array)[50] = *new int[1][50];

As for using a reference to an array: I only dynamically allocate memory
when I have to -- and here's two reasons why I'd have to:

A) I don't know how many objects I need until runtime.
B) It's just too big to put on the stack.

As was pointed many times in this and other newsgroups, in cases like
this, you're (almost) *always* better off with std::vector.

Quote:
Here's some code that just froze my PC for the last ten minutes:


#define NUMELEM(array) ( sizeof(array) / sizeof(*array) )

enum { buf_size = 999999999U /* Nearly a gigabyte */ };

int main()
{
unsigned char (&buffer)[ buf_size ] =
*new unsigned char[1][ sizeof(buffer) ];

const unsigned char* const p_last =
buffer + NUMELEM(buffer) - 1;

unsigned long i = 0;

for ( unsigned char* p = buffer; p != p_last; *p++ = i++ );

delete [] &buffer;
}

Following can freeze one's PC too, only it's shorter and more readable,
while being just as "effective".

#include <vector>
int main()
{
std::vector<char> v(999999999U, 0);
}

--
Martin

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





PostPosted: Fri May 19, 2006 10:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Ralf Fassel wrote:
Quote:
Consider:

void *foo = new int[10];
...
delete [] reinterpret_cast<char*>(foo);

Is this 'allowed' for POD types?
All of my senses say 'no', but...

R'

why did you raise this question?


my real question is: if that becomes allowed, how much useful it would
be?

cheers
Diego Martins


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





PostPosted: Fri May 19, 2006 10:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Alan McKenney wrote:
Quote:
However, following is "valid" (but still dubious)

void *foo = new int[10];
// ...
delete [] reinterpret_cast<int*>(foo); // note int*


OK, I'll bite: why is this "dubious"?

I meant that entirely losing type information is hard to justify. Not to
mention that one MUST maintain the same type name in two locations, otherwise
UB will happen.


B.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Tomás
Guest





PostPosted: Fri May 19, 2006 10:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Alan McKenney posted:


Quote:
Is static_cast<> legal here?


The following code is pefectly legal:

template<class T>
void DeletorVanilla( const void* const p )
{
delete static_cast<const T*>(p);
}

template<class T>
void DeletorArray( const void* const p )
{
delete [] static_cast<const T*>(p);
}


void PerformDeletion(const void* const p,
void (&Delete)(const void*)
)
{
Delete(p);
}

int main()
{
int * const p1 = new int;

int * const p2 = new int[5];

int (* const p3)[5] = new int [6][5];

int (* const p4)[5][7] = new int [6][5][7];


PerformDeletion( p1, DeletorVanilla<int> );

PerformDeletion( p2, DeletorArray<int> );

PerformDeletion( p3, DeletorArray<int[5]> );

PerformDeletion( p4, DeletorArray<int[5][7]> );
}


However, you can see how malloc and free are handier:


#include <cstdlib>
using std::malloc;
using std::free;

void PerformDeletion( void* const p )
{
free(p);
}

int main()
{
int * const p1 = static_cast<int*>(
malloc( sizeof(int) )
);

int * const p2 = static_cast<int*>(
malloc( sizeof(int[5]) )
);

int (* const p3)[5] = static_cast< int(*)[5] >(
malloc( sizeof(int[6][5]) )
);

int (* const p4)[5][7] = static_cast< int(*)[5][7] >(
malloc( sizeof(int[6][5][7]) )
);


PerformDeletion( p1 );

PerformDeletion( p2 );

PerformDeletion( p3 );

PerformDeletion( p4 );
}


-Tomás

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Martin Vejnár
Guest





PostPosted: Fri May 19, 2006 10:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Alan McKenney wrote:
Quote:
Bronek Kozicki wrote:
However, following is "valid" (but still dubious)

void *foo = new int[10];
// ...
delete [] reinterpret_cast<int*>(foo); // note int*

No, this is not "valid", see below.

Quote:


OK, I'll bite: why is this "dubious"?

Once you've cast it to a void *, I don't know how
else you'd delete it.

Is static_cast<> legal here?

static_cast is the only correct way to reverse a standard conversion
(save c-style cast, which would be equivalent to static_cast in this case).

reinterpret_cast is wrong here - quoting from standard - "The mapping
performed by reinterpret_cast is implementation-defined.". Following is,
however, correct:

void * foo = reinterpret_cast<void *> (new int[10]);
delete[] reinterpret_cast<int *>(foo);

This also works (and I personaly prefer static to reinterpret):

void * foo = static_cast<void *> (new int[10]);
delete[] static_cast<int *>(foo);

which is equivalent to this:

void * foo = new int[10];
delete[] static_cast<int *>(foo);

Quote:
I'll agree that good programmers try to avoid having to
write stuff like this, if they can.

Yes.

--
Martin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Martin Vejnár
Guest





PostPosted: Fri May 19, 2006 10:21 am    Post subject: Re: new/delete for different POD types? Reply with quote

Ralf Fassel wrote:
Quote:
Consider:

void *foo = new int[10];
...
delete [] reinterpret_cast<char*>(foo);

Is this 'allowed' for POD types?
All of my senses say 'no', but...

Your senses are correct, you cannot do this. When deleting an object,
its static type 'char *' must match its real (dynamic?) type 'int *'.
Formally, this is an undefined behavior.

In reality, I can't imagine this not working on PC or any other
non-embedded platform. MSVC8 simply calls free().

Also, your use of reinterpret_cast isn't very portable, as it's result
is implementation-defined. You should have used static_cast here.

--
Martin

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





PostPosted: Sat May 20, 2006 9:21 pm    Post subject: Re: new/delete for different POD types? Reply with quote

Martin Vejnár <avakar (AT) volny (DOT) cz> wrote:
Quote:
reinterpret_cast is wrong here - quoting from standard - "The mapping
performed by reinterpret_cast is implementation-defined.".

.... thus is does not have to be equivalent of static_cast conversions,
even though these two can be legally applied in some situations and seem
to deliver identical results. You are right, thanks for pointing it out.


B.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.