I’m trying to implement a technique to test failing operator new described in http://www.codeproject.com/Articles/6108/Simulating-Memory-Allocation-Failure-for-Unit-Test.
This is a sample code being tested:
VArray* arr = new VArray(1U, 3U, true);
I can make new return NULL instead of allocating memory. In this case, the program should continue to next line (which should test if arr == NULL) and this is exactly what it does in MSVC.
However, the constructor of VArray is still called after the failed new in GCC. And since this is NULL, it results in SIGSEGV on the first assignment to a property. This seems to be a wrong behavior according to C++03 standard: https://stackoverflow.com/a/11514528/711006
My implementation of operators new and delete follows.
unsigned int OperatorPlainNewFailsAfter = UINT_MAX;
void* operator new(const size_t _size) throw()
{
void* result;
if(OperatorPlainNewFailsAfter == 0U)
{
result = NULL;
}
else
{
result = malloc(_size);
OperatorPlainNewFailsAfter--;
}
return result;
}
void operator delete(void* _memory) throw()
{
free(_memory);
}
What do I miss?
The C++ standard requires that an allocation function (e.g. the basic operator new) fails by throwing a std::bad_alloc exception, if it fails. It's not allowed to return a nullpointer. When you do return a nullpointer you have Undefined Behavior, and yes, one possible consequence is that a constructor is called.
If the operator new being called is declared throw(), then
it is an error for the compiler to not check for a null pointer.
But it is illegal to declare a non-placement new throw(), so
there's no point in the compiler checking it; if anything, it
should complain when it sees the declaration, because the
non-placement operator new is implicitly declared.
If you want to test for failing new (and it's a good idea),
your operator new function shouldn't return a null pointer,
but should throw std::bad_alloc. Otherwise, you're not
testing the same thing. On the page you site, the test code
uses a placement new instead. The code is still illegal,
because his operator new may return a null pointer without
having declared the function throw(), but that is easily
fixed. (Or not. He calls ::operator new, rather than
malloc, for the actual allocation, and this function may
throw. He also calls the ::operator new function to allocate,
but used the ::delete operator de free; if you call
::operator new to allocate, you should call ::operator
delete to free.) Of course, even fixed, it doesn't test
anything useful, since what you need to know is that your
program reacts correctly to std::bad_alloc, not that it
reacts correctly to a null pointer that it will never see.
Related
I am overloading new and delete operator with custom parameters. While new works, i can't call delete with the custom parameters. I read somewhere that overloaded delete is called only if constructor of the object being created throws. If this is the case, is there no way to call my overloaded delete ?
void *operator new(size_t size, unsigned int Tag)
{
//allocate and return.
return nullptr;
}
void operator delete(void *ptr, size_t size, unsigned int Tag)
{
//deallocate
}
int main()
{
int *arr = new(123) int;
delete(123) arr;
}
error: type 'int' argument given to 'delete', expected pointer
You can't explicitly call the operator delete overload (i.e. placement delete) using delete expression. In the placement new you should save the Tag somewhere and restore it in the operator delete and deallocate the memory properly.
is there no way to call my overloaded delete ?
Yes, you can't do it explicitly.
Here's an explanation from Effective C++ (Scott Meyers, 3rd Edition), Item 52: Write placement delete if you write placement new
However, consider what happens if no exception is thrown (which will
usually be the case) and we get to a delete in client code:
delete pw; // invokes the normal
// operator delete
As the comment indicates, this calls the normal operator delete, not
the placement version. Placement delete is called only if an exception
arises from a constructor call that's coupled to a call to a placement
new. Applying delete to a pointer (such as pw above) never yields a
call to a placement version of delete. Never.
This means that to forestall all memory leaks associated with
placement versions of new, you must provide both the normal operator delete (for when no exception is thrown during construction) and a
placement version that takes the same extra arguments as operator new
does (for when one is).
I'm assuming you are defining placement-new, since your new syntax only match that one. In case of placement-delete, it is stated that:
If defined, called by the custom single-object placement new
expression with the matching signature if the object's constructor
throws an exception. (delete-operator)
Is this program supposed to compile?
int main(){
double* p = new double[4];
delete[] p;
return 0;
}
(It does compile with GCC 7.1.1)
The reason I ask this is because, I am not sure who is providing the definition of the operator new.
Is it the language? is the compiler by default #includeing <new>?
To make this question more clear I can actually define (overwrite?) operator new.
#include<cstdlib> // malloc and size_t
#include<cassert> // assert
void* operator new[](unsigned long int sz){ // what if this is not defined? who provides `new`?
assert(0); // just to check I am calling this function
return std::malloc(sz);
}
int main(){
double* p = new double[4]; // calls the new function above
delete[] p;
return 0;
}
What am I doing here?
overriding new? overloading new? Is the definition of new special (magic) for the compiler? (e.g. if not defined use a language provided one).
What is the role of #include<new> in all this?
Here you have a new expression, which invokes indeed operator new[]
void* operator new[]( std::size_t count );
The compiler is implicitly declaring the basic operator news in each translation unit (this is specified by the standard), see the cppreference documentation.
The versions (1-4) are implicitly declared in each translation unit even if the < new> header is not included.
In your second code snippet, you are overloading (technically you are actually replacing) operator new (not overriding, that's only for virtual functions), although you should overload operator new[] instead (note that if you don't, then operator new[] will fall back on operator new, so technically I believe your code is OK, but I'd just overload the array version for clarity).
There can be other overloads of operator new. You have scalar and array versions both provided by the compiler, possibly by the standard library, and possibly by user-code.
There are additional overloads of new (and delete) if you write them yourself (if they don't have the signature of the built-in versions) or if you #include new. If you provide operators that match the builtin signatures, then they will replace the builtin version. Beware. :)
The main reasons people include are for
1) constructing objects in a user-provided memory address
2) non-throwing versions of new
There are, of course, operator delete overloads as well, since new/delete must be overloaded pairwise to work together, or nearly certain destruction will follow. If your operator new matches the built-in signature, it will replace rather than overload the built-in version.
Remember, a "new expression" as simple as:
std::string myString = new std::string();
really works in 2 parts: 1) Allocating memory (via operator new), and then, 2) constructing an object in that memory. If successful, it returns the pointer to that object, and if failure, cleans up what was constructed, deallocates whatever was allocated, and then throws.
When you overload operator new, you are only dealing with the memory allocation, not the constructor call, and the object will be constructed in whatever address this operator returns. For the normal placement new, you might see code like this:
char myBuffer[1024]; // assume aligned; nobody needs more than 1024 bytes
std::string *ptr = new (myBuffer) std::string();
assert (ptr == &myBuffer);
The extra parameter to new is the myBuffer address, which is immediately returned by operator new and becomes the place where the object is constructed. The assertion should pass, and shows that the string was created in the bytes of myBuffer.
The no-throw versions of new are also available after #including new, which also uses an extra argument to the operator:
char * buf = new (std::nothrow) char[MAX_INT];
if (buf) {
std::cout << "WHOA, you have a lot of memory!!!\n";
}
Now instead of failing, it'll return a null pointer, so you have to check it.
I read this and this article and to my astonishment I found that the operator has a void* return type.
void* operator new (size_t size)
{
void *p=malloc(size);
if (p==0) // did malloc succeed?
throw std::bad_alloc(); // ANSI/ISO compliant behavior
return p;
}
But from other hand, we know, that new returns an object instead void pointer. How it is possible ?
Ok, let's make a little change to code above
void* _new (size_t size)
{
void *p=malloc(size);
if (p==0) // did malloc succeed?
throw std::bad_alloc(); // ANSI/ISO compliant behavior
return p;
}
Now, will the compiler will prevent warnings concerned with casting void* of another type?
The type of a new-expression is a pointer to the type being created. So the type of new int is int*.
operator new is a function called by a new-expression to allocate memory to store the object(s) it's creating. It returns void* because there are not yet any objects in that memory. The new-expression then creates one or more objects in that memory before yielding a correctly-typed pointer to those objects.
operator new (and the corresponding operator delete) can also be called directly to allocate raw memory. For example, the default allocator std::allocator used by the standard library's containers does this.
You've mistaken an expression containing the keyword new for an invocation of operator new.
That operator new returns void* has nothing to do with what a new-expression evaluates to!
Consider operator new to be part of the "inner mechanics" of the overall newing process.
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 can override global operator new with different parameters, so for example I can have:
void* operator new (std::size_t size) throw (std::bad_alloc);
void* operator new (std::size_t size, int num) throw (std::bad_alloc);
which can be called separately as
int* p1 = new int; // calls new(size_t)
int* p2 = new(5) int; // calls new(size_t, int)
since each of these can potentially use some different allocation scheme, I would need a separate delete() function for each. However, delete(void*) cannot be overloaded in the same way! delete(void*) is the only valid signature. So how can the above case be handled?
P.S. I am not suggesting this is a good idea. This kind of thing happened to me and so I discovered this "flaw" (at least in my opinion) in c++. If the language allows the new overrides, it must allow the delete overrides, or it becomes useless. And so I was wondering if there is a way around this, not if this a good idea.
I can override global operator new with different parameters
Those are called placement allocation functions.
delete(void*) is the only valid signature.
No.
First, some terminology: A delete expression such as delete p is not just a function call, it invokes the destructor then calls a deallocation function, which is some overload of operator delete that is chosen by overload resolution.
You can override operator delete with signatures to match your placement allocation function, but that overload will only be used if the constructor called by the placement new expression throws an exception e.g.
struct E {
E() { throw 1; }
};
void* operator new(std::size_t n, int) throw(std::bad_alloc) { return new char[n]; }
void operator delete(void* p, int) { std::puts("hello!"); delete[] (char*)p; }
int main()
{
try {
new (1) E;
} catch (...) {
puts("caught");
}
}
The placement deallocation function which matches the form of placement new expression used (in this case it has an int parameter) is found by overload resolution and called to deallocate the storage.
So you can provide "placement delete" functions, you just can't call them explicitly. It's up to you to remember how you allocated an object and ensure you use the corresponding deallocation.
If you keep track of the different memory regions you allocate with your different new overloads, you can tag them with the version of new that was called.
Then at delete time you can look the address up to find which new was called, and do something different in each case.
This way you can guarantee that the correct logic is automatically associated with each different new overload.
As pointed out by baruch in the comments below, there is a performance overhead associated with the maintenance of the data you use for tracking, and this logic will also only work as long as the overloaded delete is not passed anything allocated using the default delete.
As far as tracking overhead, it seems to me that the minimum overhead method of tracking the type of the allocation is to allocate the amount requested, plus a small amount of additional space at the start of the allocated region in which to tag the request type (sized according to conservative alignment requirements). You can then look at this tag region on delete to determine which logic to follow.
There is a placement delete which matches the placement operator new. And you can't call it directly. This is because the placement delete is only used to deallocate memory when the constructor of the new'ed object throws.
void *operator new(size_t, Area&); // placement new
void operator delete(void*, Area&); // matching placement delete
...
Area &area;
SomeType *t=new(area) SomeType();
// when SomeType() throws then `delete(t,area)` from above is called
// but you can't do this:
delete (area) t;
A common way to overcome this, is to use write an overloaded "destroy" function, which accepts all kinds of parameters.
template<class T> void destroy(Area &a, T* &pt) //<-you can't do this with 'delete'
{
if (pt) {
pt->~T(); // run the destructor
a.freeMem(pt); // deallocate the object
pt=NULL; // nulls the pointer on the caller side.
}
}
The simple answer is: Do not do this. All forms of non-placement new are redundant in C++11 and horrifically unsafe, for example, return raw pointer. If you want to allocate objects in a custom place, then use a class with an allocate function if stateful or a free function if not. The best treatment for new and indeed, delete, is to excise them from your program with prejudice, with the possible exception of placement new.
Edit: The reason why it's useless for you is because you're trying to use it for a purpose which it was not intended for. All you can use the extra params for is stuff like logging or other behaviour control. You can't really change the fundamental semantics of new and delete. If you need stateful allocation, you must use a class.
You're wrong. It is possible to provide a placement delete.