 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Ralf Fassel Guest
|
Posted: Wed May 17, 2006 10:21 am Post subject: new/delete for different POD types? |
|
|
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
|
Posted: Wed May 17, 2006 3:21 pm Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Wed May 17, 2006 3:21 pm Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Wed May 17, 2006 3:21 pm Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Wed May 17, 2006 10:21 pm Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Thu May 18, 2006 2:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Thu May 18, 2006 2:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Thu May 18, 2006 1:21 pm Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Fri May 19, 2006 10:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Fri May 19, 2006 10:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Fri May 19, 2006 10:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Fri May 19, 2006 10:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Fri May 19, 2006 10:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Fri May 19, 2006 10:21 am Post subject: Re: new/delete for different POD types? |
|
|
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
|
Posted: Sat May 20, 2006 9:21 pm Post subject: Re: new/delete for different POD types? |
|
|
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 |
|
 |
|
|
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
|
|