473,385 Members | 1,356 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

using delete expression on global operator new allocated memory

Hi

I wonder if this code is standard conformant and should work on all
conformant implementations (for some type T):

1: void* mem = ::operator new(sizeof(T));
2: T* p = new(mem) T(args...);
3: delete p;

line 2 I know it should be fine because global operator new should return
memory aligned for any type. The thing I wonder about is line 3. Should
this always work?

PS: the code might seem silly, it is needed because I need to decouple the
point of storage type used (which on 2 different codepaths can be on stack
or dynamic) from the point of actual initialization of the object and its
arguments (thus I need to use placement new); another solution I am aware
of whould be using some kind of "factory functors" (like the ones in boost)
but that would require for me to use template functions which is what I
want to avoid in the first place

--
Dizzy

Jun 27 '08 #1
3 1740
On 30 huhti, 13:07, dizzy <di...@roedu.netwrote:
PS: the code might seem silly
It is silly.
Jun 27 '08 #2
On Apr 30, 12:07 pm, dizzy <di...@roedu.netwrote:
I wonder if this code is standard conformant and should work on all
conformant implementations (for some type T):
1: void* mem = ::operator new(sizeof(T));
2: T* p = new(mem) T(args...);
3: delete p;
line 2 I know it should be fine because global operator new
should return memory aligned for any type. The thing I wonder
about is line 3. Should this always work?
I think so, but I think the point is vague enough that I'd avoid
counting on it. The usual rule is to separate destruction and
deallocation anytime you've separated allocation and
initialization. In other words, you sould probably replace 3
with:

p->~T() ;
::operator delete( p ) ;
PS: the code might seem silly, it is needed because I need to
decouple the point of storage type used (which on 2 different
codepaths can be on stack or dynamic) from the point of actual
initialization of the object and its arguments (thus I need to
use placement new);
I'm not sure I understand this. If the object is on the stack,
it will have been constructed where it was declared, and will be
destructed when it goes out of scope. So you can't use
placement new on it later, and you can't explicitly delete it
in any way.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #3
James Kanze wrote:
I think so, but I think the point is vague enough that I'd avoid
counting on it. The usual rule is to separate destruction and
deallocation anytime you've separated allocation and
initialization. In other words, you sould probably replace 3
with:

p->~T() ;
::operator delete( p ) ;
That doesn't work the way I do things (explanation below).
I'm not sure I understand this. If the object is on the stack,
it will have been constructed where it was declared, and will be
destructed when it goes out of scope. So you can't use
placement new on it later, and you can't explicitly delete it
in any way.
But it exists in a possible call algorithm. So I will give more details
about the code.

Supose I have a hierarchy of user defined types, DerivedX (with X being from
1 to 3) inherited from Base. The contents of a DerivedX at some point it is
serialized somehow (say by first storing some kind of numeric value that
associates the type stored and then the contents of the type). When I do
deserialization obviously I need to read that value and then deserialize
the actual type that I know follows in the input stream by using a ctor of
the deserialized type that receives various arguments which arguments are
first deserialized. I cannot just make a ctor version for each
deserializable type that takes the stream type as argument and it will
construct by deserialization from the stream and I cannot do something like
overloading some operator<< on my stream types because there are many ways
the objects are serialized/deserialized and they don't all depend on the
stream type used (or making such stream types for each way would be
pointless). So each way to deserialize has an API that will do it and
considering one such way/API it should be able to provide 2 ways to do it:

- one way, more straightforward and OOP (especially since all are inherited
from a common base) is to have something like this:
auto_ptr<Nodeload(InputStream& is);

Which obviously will read the type, will switch/case on it and then will
deserialize the arguments needed for the ctor and then do something like
return auto_ptr<Node>(new DerivedX(args...)); (where X will be dependent on
the read numeric value that associates the serialized type)

While fine from an OOP perspective this code fails in many other aspects
because it will "lose" the actual type it was dereferenced and will return
a (smart) pointer to the Base class thus forcing the callers to use some
method (say a Visitor aproach) to identify the type again and perform
actual work on the specific type. So then I said, I should have another API
that does not lose the type.

- the second way to perform object deserialization is to have a load like
this:
template<typename Function>
void load(InputStream& is, Function func);

In this second case, "load" will read again (from the stream) the numeric
value that identifies the serialized type, then again will deserialize the
arguments specific to this type and then will create locally (on stack) an
object of the specific type using the deserialized arguments and will call
func(thatobject) (so Function needs to have an operator() taking each
possible obeject type). This is like a callback algorithm but avoiding the
costs of using boost::function (or other such generic functor) because the
callback happens with normal function call resolved at compile time and
will also avoid a costly Visitor aproach to get the type lost from the
first "load" version.

In both "load" versions I need to read the numeric value, switch/case on it
and then deserialize the arguments specific to the type and then construct
the type from those arguments. Using the original question method I could
decouple the reading of arguments/construction from the actual object
storage without having the functions that do the actual read be templates
(which I want to avoid) but they could just be something like:
Derived0*
loadDerived0(InputStream& is, void* where) {
// deserialize specific Derived0 arguments
return new(where) Derived0(args...);
}

The callers of these functions can either come from the codepath with
the "functor" argument, in which case they allocated properly aligned
storage on the stack and they will call the functor with argument on the
initialized object and then get rid of it or they come from the codepath
with the load returning auto_ptr<Basein which case they will allocate
memory aligned for anything with ::operator new(sizeof(DerivedX)); and will
return an auto_ptr to it. And as such at some point auto_ptr will call
delete on the ::operator new returned memory which I need to know if it is
valid code.

--
Dizzy

Jun 27 '08 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: A | last post by:
Hi, Consider this: char* ptr = "a string"; Is ptr a pointer to a dynamically created object for which i must use the delete operator to deallocate memory? I'm sure the "a string" part...
25
by: rokia | last post by:
in a project, I use many,many stl such as stack,list,vctor etc. somewhere the vector's size is more than 2K. is this a efficient way?
20
by: Ioannis Vranos | last post by:
When we use the standard placement new operator provided in <new>, and not a definition of owr own, isn't a call to placement delete enough? Consider the code: #include <new>
10
by: Neelesh Bodas | last post by:
Hi all, suppose the ctor of the class throws. Thus, at this point in time, some memory has been allocated but the object couldnot be constructed. Also, the memory is not yet freed. Does the c++...
4
by: AndrewD | last post by:
Hey C++ folks, I created this today, just for fun. You can make object allocation for any class around 6 times faster, simply by doing the following. class MyClass : public...
12
by: yufufi | last post by:
Hello, How does delete know how much memory to deallocate from the given pointer? AFAIK this informations is put there by new. new puts the size of the allocated memory before the just before...
71
by: desktop | last post by:
I have read in Bjarne Stroustrup that using malloc and free should be avoided in C++ because they deal with uninitialized memory and one should instead use new and delete. But why is that a...
13
by: Tristan Wibberley | last post by:
Hi I've got implementing overloaded operator new and delete pretty much down. Just got to meet the alignment requirements of the class on which the operator is overloaded. But how does one...
6
by: mthread | last post by:
Hi, I am learning C++ and I have been told that an object can be created either by using calloc or new. If it is true, can some one tell me what is the difference b/w using these two function...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.