Is it possible in c++ to allocate an object at a specific place in memory? I'm implementing my hobby os kernel memory manager which gives void* addresses to store my stuff and I would like to know how can I use that pointer to allocate my object there. I have tried this:
string* s = (string*)235987532//Whatever address is given.
*s = string("Hello from string\n\0");//My own string class
//This seems to call the strings destructor here even thought I am using methods from s after this in my code...
The only problem with this is that it calls string objects destructor which it shouldn't do. Any help is appreciated.
EDIT: I cannot use placement new because I'm developing in kernel level.
Assignment only works if there's a valid object there already. To create an object at an arbitrary memory location, use placement new:
new (s) string("Hello");
Once you've finished with it, you should destroy it with an explicit destructor call
s->~string();
UPDATE: I just noticed that your question stipulates "without placement new". In that case, the answer is "you can't".
You need to use placement new. There is not an alternative, because this is precisely what placement new is for.
I think you should be able to first implement the operator new used by placement new:
void* operator new (std::size_t size, void* ptr) noexcept
{
return ptr;
}
(See [new.delete.placement] in C++11)
Then, you can use placement new the way it's intended to.
you can use placement new allocation
void* memory = malloc(sizeof(string));
string* myString = new (memory) string();
source: What is an in-place constructor in C++?
Related
I've been reading some questions about placement new on SO and I am finding some different ways to use it that I thought I would ask about here. I understand that placement new is basically a way for you to create an object and give it a certain place in memory of your choice that has already been allocated; I just don't understand all of the intricacies.
First one I saw on SO uses this example (from C++ Primer):
const int BUF = 512;
const int N = 5;
char buffer[BUF];
double * pd1;
pd1 = new (buffer) double[N];
Second one I saw on SO uses this example (from C++ Primer Plus):
char * buffer = new char[BUF]; //get a block of memory
JustTesting *pc1, *pc2;
pc1 = new (buffer) JustTesting; //Place object in buffer
The main difference between these two is that in the first block of code, buffer is a char array and in the second example it is a pointer to a char array, yet both blocks of code contain new (buffer).
My first question is: When using placement new in this context, can it accept either an object or it's address, and if so, is one preferred?
I've also seen placement new used without an lvalue. See below.
new(&myObject) myClass;
My second question is: What are the differences between placement new with vs. without an lvalue?
I understand that placement new is basically a way for you to create an object and give it a certain place in memory of your choice that has already been allocated;
Not exactly.
new expression calls the corresponding operator new and then invokes the constructor. Note that these are two different things named similarly.
Placement new expression skips allocating memory and only invokes the constructor. This is achieved by using the placement void* operator new( std::size_t count, void* ptr), which does nothing and returns ptr.
It is your job to provide storage for the object being initialized when using placement new.
Your first question is already answered. For your 2nd question - What are the differences between placement new with vs. without an lvalue?
Since placement new returns the address that is passed in its 2nd parameter, requiring an lvalue to store that address is optional. See the placement new implementation below from Microsoft Visual Studio-
inline void *__CRTDECL operator new(size_t, void *_Where) _THROW0()
{ // construct array with placement at _Where
return (_Where);
}
I am in need to write / overload / override default C++ new operator. I found this below information -
non-allocating placement allocation functions
void* operator new ( std::size_t count, void* ptr );
(9)
void* operator new[]( std::size_t count, void* ptr );
(10)
As per documentation it state -
Called by the standard single-object placement new expression. The standard library implementation performs no action and returns ptr unmodified.
I am not able to clear myself by what is meant by "non-allocating placement allocation functions"?
These overloads are used by placement new. This is an expression that creates an object at a memory location, but doesn't allocate space for it. For instance, in this toy example:
void foo() {
void *raw = malloc(sizeof(int));
int *pint = new(raw) int(10);
pint->~int();
free(raw);
}
This illustrates that if we need to create an object in memory allocated by something that is not the C++ standard library (in this case, the C allocation functions), special syntax is used to create an object at that location.
The placement operator new accepts the address, and returns it unchanged. Thus the new expression just creates an object there. Naturally, we cannot call delete to free said object and memory, we must do an explicit destructor call, followed by the correct memory deallocation function.
Non-allocating placement allocation function is a form of new that doesn't allocate memory, but rather constructs an object in pre-allocated memory.
See this answer for more details.
To answer the question implied in your title:
It is not permitted to supply your own replacement function for the non-allocating forms of operator new. This is covered in the standard (N4659):
Non-allocating forms [new.delete.placement]
These functions are reserved; a C++ program may not define functions that displace the versions in the C++ standard library.
You can only replace the forms of operator new which are listed as Replacable under the section of the Standard labelled [new.delete].
(C++/Win32)
consider the following call:
Object obj = new Object(a,b);
other than allocating the virtual memory needed for an instance of an Object, what else is going on under the hood up there? does the compiler places an explicit call to the constructor of Object?
is there any way to initialize a c++ object dynamically without the use of the keyword new?
If you want to initialize an object in some given memory zone, consider the placement new (see this)
BTW, the ordinary Object* n = new Object(123) expression is nearly equivalent to (see operator ::new)
void* p = malloc(sizeof(Object));
if (!p) throw std::bad_alloc;
Object* n = new (p) Object(123); // placement new at p,
// so invokes the constructor
But the implementation could use some non-malloc compatible allocator, so don't mix new and free!
You can always use malloc instead of new, but don't forget to always couple it with free and not delete.
See also :
What is the difference between new/delete and malloc/free?
In his new book TC++PL4, Stroustrup casts a slightly different light on a once usual practice regarding user-controlled memory allocation and placement new—or, more specifically, regarding the enigmatical "placement delete." In the book's sect. 11.2.4, Stroustrup writes:
The "placement delete" operators do nothing except possibly inform a garbage collector that the deleted pointer is no longer safely derived.
This implies that sound programming practice will follow an explicit call to a destructor by a call to placement delete.
Fair enough. However, is there no better syntax to call placement delete than the obscure
::operator delete(p);
The reason I ask is that Stroustrup's sect. 11.2.4 mentions no such odd syntax. Indeed, Stroustrup does not dwell on the matter; he mentions no syntax at all. I vaguely dislike the look of ::operator, which interjects the matter of namespace resolution into something that properly has nothing especially to do with namespaces. Does no more elegant syntax exist?
For reference, here is Stroustrup's quote in fuller context:
By default, operator new creates its object on the free store. What
if we wanted the object allocated elsewhere?... We can place objects
anywhere by providing an allocator function with extra arguments and
then supplying such extra arguments when using new:
void* operator new(size_t, void* p) { return p; }
void buf = reinterpret_cast<void*>(0xF00F);
X* p2 = new(buf) X;
Because of this usage, the new(buf) X syntax for supplying extra
arguments to operator new() is known as the placement syntax.
Note that every operator new() takes a size as its first argument
and that the size of the object allocated is implicitly supplied.
The operator new() used by the new operator is chosen by the
usual argument-matching rules; every operator new() has
a size_t as its first argument.
The "placement" operator new() is the simplest such allocator. It
is defined in the standard header <new>:
void* operator new (size_t, void* p) noexcept;
void* operator new[](size_t, void* p) noexcept;
void* operator delete (void* p, void*) noexcept; // if (p) make *p invalid
void* operator delete[](void* p, void*) noexcept;
The "placement delete" operators do nothing except possibly inform a
garbage collector that the deleted pointer is no longer safely
derived.
Stroustrup then continues to discuss the use of placement new with arenas. He does not seem to mention placement delete again.
If you don't want to use ::, you don't really have to. In fact, you generally shouldn't (don't want to).
You can provide replacements for ::operator new and ::operator delete (and the array variants, though you should never use them).
You can also, however, overload operator new and operator delete for a class (and yes, again, you can do the array variants, but still shouldn't ever use them).
Using something like void *x = ::operator new(some_size); forces the allocation to go directly to the global operator new instead of using a class specific one (if it exists). Generally, of course, you want to use the class specific one if it exists (and the global one if it doesn't). That's exactly what you get from using void *x = operator new(some_size); (i.e., no scope resolution operator).
As always, you need to ensure that your news and deletes match, so you should only use ::operator delete to delete the memory when/if you used ::operator new to allocate it. Most of the time you shouldn't use :: on either one.
The primary exception to that is when/if you're actually writing an operator new and operator delete for some class. These will typically call ::operator new to get a big chunk of memory, then divvy that up into object-sized pieces. To allocate that big chunk of memory, it typically (always?) has to explicitly specify ::operator new because otherwise it would end up calling itself to allocate it. Obviously, if it specifies ::operator new when it allocates the data, it also needs to specify ::operator delete to match.
First of all: No there isn't.
But what is the type of memory? Exactly, it doesn't have one. So why not just use the following:
typedef unsigned char byte;
byte *buffer = new byte[SIZE];
Object *obj1 = new (buffer) Object;
Object *obj2 = new (buffer + sizeof(Object)) Object;
...
obj1->~Object();
obj2->~Object();
delete[] buffer;
This way you don't have to worry about placement delete at all. Just wrap the whole thing in a class called Buffer and there you go.
EDIT
I thought about your question and tried a lot of things out but I found no occasion for what you call placement delete. When you take a look into the <new> header you'll see this function is empty. I'd say it's just there for the sake of completeness. Even when using templates you're able to call the destructor manually, you know?
class Buffer
{
private:
size_t size, pos;
byte *memory;
public:
Buffer(size_t size) : size(size), pos(0), memory(new byte[size]) {}
~Buffer()
{
delete[] memory;
}
template<class T>
T* create()
{
if(pos + sizeof(T) > size) return NULL;
T *obj = new (memory + pos) T;
pos += sizeof(T);
return obj;
}
template<class T>
void destroy(T *obj)
{
if(obj) obj->~T(); //no need for placement delete here
}
};
int main()
{
Buffer buffer(1024 * 1024);
HeavyA *aObj = buffer.create<HeavyA>();
HeavyB *bObj = buffer.create<HeavyB>();
if(aObj && bObj)
{
...
}
buffer.destroy(aObj);
buffer.destroy(bObj);
}
This class is just an arena (what Stroustrup calls it). You can use it when you have to allocate many objects and don't want the overhead of calling new everytime. IMHO this is the only use case for a placement new/delete.
This implies that sound programming practice will follow an explicit call to a destructor by a call to placement delete.
No it doesn't. IIUC Stroustrup does not mean placement delete is necessary to inform the garbage collector that memory is no longer in use, he means it doesn't do anything apart from that. All deallocation functions can tell a garbage colector memory is no longer used, but when using placement new to manage memory yourself, why would you want a garbage collector to fiddle with that memory anyway?
I vaguely dislike the look of ::operator, which interjects the matter of namespace resolution into something that properly has nothing especially to do with namespaces.
"Properly" it does have to do with namespaces, qualifying it to refer to the "global operator new" distinguishes it from any overloaded operator new for class types.
Does no more elegant syntax exist?
You probably don't ever want to call it. A placement delete operator will be called by the compiler if you use placement new and the constructor throws an exception. Since there is no memory to deallocate (because the pacement new didn't allocate any) all it does it potentially mark the memory as unused.
I was looking at the signature of new operator. Which is:
void* operator new (std::size_t size) throw (std::bad_alloc);
But when we use this operator, we never use a cast. i.e
int *arr = new int;
So, how does C++ convert a pointer of type void* to int* in this case. Because, even malloc returns a void* and we need to explicitly use a cast.
There is a very subtle difference in C++ between operator new and the new operator. (Read that over again... the ordering is important!)
The function operator new is the C++ analog of C's malloc function. It's a raw memory allocator whose responsibility is solely to produce a block of memory on which to construct objects. It doesn't invoke any constructors, because that's not its job. Usually, you will not see operator new used directly in C++ code; it looks a bit weird. For example:
void* memory = operator new(137); // Allocate at least 137 bytes
The new operator is a keyword that is responsible for allocating memory for an object and invoking its constructor. This is what's encountered most commonly in C++ code. When you write
int* myInt = new int;
You are using the new operator to allocate a new integer. Internally, the new operator works roughly like this:
Allocate memory to hold the requested object by using operator new.
Invoke the object constructor, if any. If this throws an exception, free the above memory with operator delete, then propagate the exception.
Return a pointer to the newly-constructed object.
Because the new operator and operator new are separate, it's possible to use the new keyword to construct objects without actually allocating any memory. For example, the famous placement new allows you to build an object at an arbitrary memory address in user-provided memory. For example:
T* memory = (T*) malloc(sizeof(T)); // Allocate a raw buffer
new (memory) T(); // Construct a new T in the buffer pointed at by 'memory.'
Overloading the new operator by defining a custom operator new function lets you use new in this way; you specify how the allocation occurs, and the C++ compiler will wire it into the new operator.
In case you're curious, the delete keyword works in a same way. There's a deallocation function called operator delete responsible for disposing of memory, and also a delete operator responsible for invoking object destructors and freeing memory. However, operator new and operator delete can be used outside of these contexts in place of C's malloc and free, for example.
You confuse new expression with operator new() function. When the former is compiled the compiler among other stuff generates a call to operator new() function and passes size enough to hold the type mentioned in the new expression and then a pointer of that type is returned.