I made a couple macros to make using placement new a bit easier. I was just wondering if there were any obvious cases where these would not work. Thanks.
#define CONSTRUCT_INPLACE(TYPE,STORAGE,INIT) ::new((TYPE*)STORAGE) TYPE INIT
#define DESTRUCT_INPLACE(TYPE,STORAGE) ((TYPE*)STORAGE)->~TYPE()
I'm not an expert in placement new but there are a couple of issues with how you are defining the macro.
Issue 1
The most obvious problem is the use of the cast (TYPE*)STORAGE for the storage location. This is incorrect. Placement new is just another C++ function and it participates in operations like overload resolution. Arbitrarily casting the memory to a specific type could cause the placement new to bind to a different operator new that the user expected.
For example, it's valid to have the following two definitions of placement new. Your macro would potentially cause the wrong one to be called.
void * _cdecl operator new(size_t cbSize, void* pv);
void * _cdecl operator new(size_t cbSize, SomeType* pv)-
...
// These two call different overloads
void* p = malloc(sizeof(SomeType));
SomeType* f1 = CONSTRUCT_INPLACE(SomeType, p,())
SomeType* f2 = new (p) SomeType();
I wrote a blog post awhile back on how you can use this type of overload resolution to implement custom allocators.
http://blogs.msdn.com/jaredpar/archive/2007/10/17/c-placement-new-and-allocators.aspx
Issue 2
The expression STORAGE in the macro should be wrapped in parens to prevent evil macro expansion bugs.
::new((TYPE*)(STORAGE)) TYPE INIT
In addition to issues stated elsewhere your macros interact very badly (i.e. fail to compile) with template types.
In general, macros should be avoided when there is no clear benefit. To be brutally honest, I can't see a real benefit here.
e.g.
template< class A, class B >
class T
{
public:
T(A y, B z) : x(y), w(z) {}
A x;
B w;
};
int main()
{
void* p = ::operator new(sizeof(T));
CONSTRUCT_INPLACE(T<int, double>, p, (4, 5.0));
DESTRUCT_INPLACE(T<int, double>, p);
::operator delete(p);
return 0;
}
Looking at them, I wonder what that first (TYPE*) cast is for - placement new takes a void*, after all.
But then again, I wonder what they are good for at all. All they manage is to further obfuscate something that isn't really trivial to begin with. Why do you think you need them?
That being said, have you looked at the (admittedly few) standard library facilities for dealing with uninitialized memory? (See the lower half of this website. There might be something you can use.
Your CONSTRUCT_INPLACE seems a bit odd to me. Usage would be:
void* p = <some memory location>;
Foo* f = CONSTRUCT_INPLACE(Foo, p, Foo())
// The macro-free version seems easier to read:
Foo* f = new(p) Foo();
DESTRUCT_INPLACE is at least easier to read than the code it replaces.
But really, why are you doing so much placement new that these macros are of use to you? Put that stuff in a pool class and forget about it.
Placement-new operator creates an object in what initially is a block of "raw" memory. I.e. the proper type for the memory pointer passed to the placement new is 'void*'. Casting it to type '(TYPE*)', as you do, is harmless, but useless. What is the point of the cast in your 'DESTRUCT' macro is also not immediately clear.
BTW, what is the point of having these macros at all? You say they "make using placement new a bit easier", but all they seem to do is perform some completely unnecessary casts.
Related
Is it good practice to access a pointer variable by dereferencing a pointer to a pointer, which points to a different type or void? Could this break strict aliasing rules? C and C++ have some differences in aliasing rules. In this question we focus on C++. The other question considering C can be found here. In the following example a double* is accessed as a void*.
int create_buffer(void** ptr, ...)
{
*ptr = malloc(...);
...
}
int main(void)
{
double* buffer;
// The problematic code is here, double**
// is coerced to void**, which is later
// dereferenced by the function
create_buffer(reinterpret_cast<void**>(&buffer), ...);
...
}
If this is causes UB, what about the following?
// process A
int* p; ...
printf("%p", p); // UB?
// process B
int* p;
scanf("%p", &p); // UB?
This looks like a bad example, but what if two processes talk to each other through pipes, and eventually one process passes a pointer to globally allocated memory to the other process.
Is it good practice to access...
No. void* is not the go to type for polymorphism and reuse in C++, even without considering the aliasing issues in your original code. With a rich template mechanism available you can make your code strongly typed and safer to boot. The obvious improvement is to use templates, and type safe allocation:
template<typename T>
int create_buffer(T** ptr, ...)
{
*ptr = new T[...];
...
}
But to go off on a tangent, this is still not how good C++ will look like. Good C++ is about managing complexity correctly. And tracking a buffer is a complex task. The good C++ approach is to not do it by hand, but to encapsulate it in a dedicated class (template). In fact, this is such a common task, that the standard library provides a solution.
The good practice is to use std::vector<double> instead of the buffer creation function. A class template for a type generic task will often beat any use of void*. That will avoid any aliasing issues entirely, since the correct type is always used.
This is UB as you are assigning a double* variable as if it was a void* variable (It has the same effect as reinterpret_cast<void*&>(buffer) = malloc(...); in C++. This would be OK on most systems as void* and double* are usually exactly the same, but it is still UB, so might not work on all implementations).
A solution would be to assign to a different variable and then reassign it:
int main(void)
{
double* buffer;
{
void* result;
create_buffer(&result, ...);
buffer = (double*) result; // Cast needed for C++
}
...
}
struct run_male_walker_struct {
string male_user_name;
string show_name;
};
typedef struct run_male_walker_struct run_male_walker_struct_t;
in another function:
run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct));
question, is it illegal? As the string is a class, it's size can't be determined by sizeof().
This is illegal, but not for the reasons you're thinking.
The difference between std::malloc()/std::free() and new/delete is that the latter will call constructors/destructors, while the former won't. The expression
void* p = std::malloc(sizeof(run_male_walker_struct))
will return a blob of uninitialized memory on which no constructor is called. You shouldn't touch it with a ten foot pole - except for invoking a constructor on it:
run_male_walker_struct* pw = new(p) run_male_walker_struct;
If you do this, you will have to do the reverse, too:
pw->~run_male_walker_struct();
before you free the memory:
std::free(p);
However, that leaves the question why you want to do that.
The only reason to do this should be when you want to separate memory allocation from construction (like, for example, in a pool allocator). But if you need that, it's best hidden behind some interface. A natural one would be overloading new and delete per class. Also, std::vector does this internally.
Not really sure what you're asking here... Just to be clear, the struct keyword is a valid C++ designation, that functions nearly identically to class except for the default privacy. So if you're compiling with g++, and including the string library, this is a valid statement.
However, calling with malloc() will just give you the memory, not actually construct the values inside that struct. You could more appropriately instantiate it by calling it's default constructor.
The struct definition itself is fine. It results is a non-POD aggregate. But you should prefer the use of new and delete over malloc and free because these handle construction and destruction properly. If you want to keep using malloc and free you have to use the placement-new to properly construct the object and invoke the destructor manually to destroy it before you free it:
#include <new>
...
run_male_walker_struct *p = (run_male_walker_struct*)
malloc(sizeof(run_male_walker_struct));
new(p) run_male_walker_struct; // <-- placement-new
...
p->~run_male_walker_struct(); // <-- pseudo destructor call
free(p);
Or simply:
run_male_walker_struct *p = new run_male_walker_struct;
...
delete p;
BTW: the typedef is not necessary in C++
Try not to use malloc, if you are in C++.
Using NEW is a better alternative, when you browse into the NEW() code, you will realize it does call malloc!!!
The pros of using NEW is it will call the constructor of your class instantiated.
Another minor comment, the code you provided should not be compilable:
run_male_walker_struct_t *p = malloc(sizeof(struct run_male_walker_struct));
Should be
run_male_walker_struct_t *p = (run_male_walker_struct_t*)malloc(sizeof(struct run_male_walker_struct));
this is due to malloc will return a void*.
Using malloc() would work, but using it will only create enough space for your struct.
This means that you will not be able to use your strings properly, because they weren't initialised with their constructors.
Note that string classes don't have their contents in stack memory, but in dynamic memory, which doesn't affect the size of the struct. All classes and structs have a static size, that are known at compile-time (if the struct/class was defined).
I would suggest using new. Using malloc will stuff up the strings.
This raises a question of my own, how did constructors get called on dynamically allocated instantiation in C (were there no such things as constructors in C?). If so, yet another reason against using pure C.
How about
run_male_walker_struct_t * p = new run_male_walker_struct_t:
I'm fairly sure this is legal because the size of the std::string object will be known even if the lengths of the strings are not known. The results may not be what you expect though because malloc won't call constructors.
Try this:
std::string testString1("babab");
std::string testString2("12345678");
std::string testString3;
std::cout <<" sizeof(testString1)" <<sizeof(testString1) << std::endl;
std::cout <<" sizeof(testString2)" <<sizeof(testString2) << std::endl;
std::cout <<" sizeof(testString3)" <<sizeof(testString3) << std::endl;
On my machine this gives me the following output:
sizeof(testString1)8
sizeof(testString2)8
sizeof(testString3)8
Also is there some reason you are not using:
run_male_walker_struct_t *p = new(struct run_male_walker_struct);
This is the correct way to do it in c++, using malloc is almost certainly a mistake.
EDIT: see this page for a more detailed explanation of new vs malloc in c++:
http://www.codeproject.com/KB/tips/newandmalloc.aspx
The answer depends on what you mean by a "C struct".
If you mean "a struct that is valid under the C language", then the answer is obviously: it contains a datatype that isn't valid C, and so the struct itself isn't valid either.
If you mean a C++ POD type, then the answer is no, it is not illegal, but the struct is no longer a POD type (because in order to be POD, all its members must be POD as well, and std::string isn't)
I'm working with a class for which the new operator has been made private, so that the only way to get an instance is to write
Foo foo = Foo()
Writing
Foo* foo = new Foo()
does not work.
But because I really want a pointer to it, I simulate that with the following :
Foo* foo = (Foo*)malloc(sizeof(Foo));
*foo = Foo();
so that can test whether the pointer is null to know whether is has already been initialized.
It looks like it works, from empirical tests, but is it possible that not enough space had been allocated by malloc ? Or that something else gets funny ?
--- edit ---
A didn't mention the context because I was not actually sure about why they the new operator was disabled. This class is part of a constraint programming library (gecode), and I thought it may be disabled in order to enforced the documented way of specifying a model.
I didn't know about the Concrete Data Type idiom, which looks like a more plausible reason.
That allocation scheme may be fine when specifying a standard model --- in which everything is specified as CDTs in the Space-derived class --- but in my case, these instance are each created by specific classes and then passed by reference to the constructor of the class that reprensents the model.
About the reason i'm not using the
Foo f;
Foo *pf = &f;
it would be like doing case 1 below, which throws a "returning reference to local variable" warning
int& f() { int a=5; return a; } // case 1
int& f() { int a=5; int* ap=&a; return *ap; }
int& f() { int* ap=(int*)malloc(sizeof(int)); *ap=5; return *ap; }
this warning disappears when adding a pointer in case 2, but I guess it is because the compiler loses tracks.
So the only option left is case 3 (not mentioning that additionaly, ap is a member of a class that will be initialized only once when f is called, will be null otherwise, and is the only function returning a reference to it. That way, I am sure that ap in this case when lose its meaning because of the compilier optimizing it away (may that happen ?)
But I guess this reaches far too much beyond the scope of the original question now...
Don't use malloc with C++ classes. malloc is different from new in the very important respect that new calls the class' constructor, but malloc does not.
You can get a pointer in a couple ways, but first ask yourself why? Are you trying to dynamically allocate the object? Are you trying to pass pointers around to other functions?
If you're passing pointers around, you may be better off passing references instead:
void DoSomething(Foo& my_foo)
{
my_foo.do_it();
}
If you really need a pointer (maybe because you can't change the implementation of DoSomething), then you can simply take the pointer to an automatic:
Foo foo;
DoSomething(&foo);
If you need to dynamically allocate the Foo object, things get a little trickier. Someone made the new operation private for a reason. Probably a very good reason. There may be a factory method on Foo like:
class Foo
{
public:
static Foo* MakeFoo();
private:
};
..in which case you should call that. Otherwise you're going to have to edit the implementation of Foo itself, and that might not be easy or a good thing to do.
Be careful about breaking the Concrete Data Type idiom.
You are trying to circumvent the fact that the new operator has been made private, i.e. the Concrete Data Type idiom/pattern. The new operator was probably made private for specific reasons, e.g. another part of the design may depend on this restriction. Trying to get around this to dynamically allocate an instance of the class is trying to circumvent the design and may cause other problems or other unexpected behavior. I wouldn't suggest trying to circumvent this without studying the code thoroughly to ensure you understand the impact to other parts of the class/code.
Concrete Data Type
http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#ConcreteDataType
Solutions
...
Objects that represent abstractions that live "inside" the program, closely tied to the computational model, the implementation, or the programming language, should be declared as local (automatic or static) instances or as member instances. Collection classes (string, list, set) are examples of this kind of abstraction (though they may use heap data, they themselves are not heap objects). They are concrete data types--they aren't "abstract," but are as concrete as int and double.
class ScopedLock
{
private:
static void * operator new (unsigned int size); // Disallow dynamic allocation
static void * operator new (unsigned int size, void * mem); // Disallow placement new as well.
};
int main (void)
{
ScopedLock s; // Allowed
ScopedLock * sl = new ScopedLock (); // Standard new and nothrow new are not allowed.
void * buf = ::operator new (sizeof (ScopedLock));
ScopedLock * s2 = new(buf) ScopedLock; // Placement new is also not allowed
}
ScopedLock object can't be allocated dynamically with standard uses of new operator, nothrow new, and the placement new.
The funny thing that would happen results from the constructor not being called for *foo. It will only work if it is a POD (simple built-in types for members + no constructor). Otherwise, when using assignment, it may not work out right, if the left-hand side is not already a valid instance of the class.
It seems, you can still validly allocate an instance on the heap with
Foo* p = ::new Foo;
To restrict how a class instance can be created, you will probably be better off declaring the constructor(s) private and only allow factory functions call them.
Wrap it:
struct FooHolder {
Foo foo;
operator Foo*() { return &foo; }
};
I don't have full understanding of the underlying code. If other things are ok, the code above is correct. Enough space will be allocated from malloc() and anything funny will not happen. But avoid using strange code and work straighforward:
Foo f;
Foo *pf = &f;
I've recently come across this rant.
I don't quite understand a few of the points mentioned in the article:
The author mentions the small annoyance of delete vs delete[], but seems to argue that it is actually necessary (for the compiler), without ever offering a solution. Did I miss something?
In the section 'Specialized allocators', in function f(), it seems the problems can be solved with replacing the allocations with: (omitting alignment)
// if you're going to the trouble to implement an entire Arena for memory,
// making an arena_ptr won't be much work. basically the same as an auto_ptr,
// except that it knows which arena to deallocate from when destructed.
arena_ptr<char> string(a); string.allocate(80);
// or: arena_ptr<char> string; string.allocate(a, 80);
arena_ptr<int> intp(a); intp.allocate();
// or: arena_ptr<int> intp; intp.allocate(a);
arena_ptr<foo> fp(a); fp.allocate();
// or: arena_ptr<foo>; fp.allocate(a);
// use templates in 'arena.allocate(...)' to determine that foo has
// a constructor which needs to be called. do something similar
// for destructors in '~arena_ptr()'.
In 'Dangers of overloading ::operator new[]', the author tries to do a new(p) obj[10]. Why not this instead (far less ambiguous):
obj *p = (obj *)special_malloc(sizeof(obj[10]));
for(int i = 0; i < 10; ++i, ++p)
new(p) obj;
'Debugging memory allocation in C++'. Can't argue here.
The entire article seems to revolve around classes with significant constructors and destructors located in a custom memory management scheme. While that could be useful, and I can't argue with it, it's pretty limited in commonality.
Basically, we have placement new and per-class allocators -- what problems can't be solved with these approaches?
Also, in case I'm just thick-skulled and crazy, in your ideal C++, what would replace operator new? Invent syntax as necessary -- what would be ideal, simply to help me understand these problems better.
Well, the ideal would probably be to not need delete of any kind. Have a garbage-collected environment, let the programmer avoid the whole problem.
The complaints in the rant seem to come down to
"I liked the way malloc does it"
"I don't like being forced to explicitly create objects of a known type"
He's right about the annoying fact that you have to implement both new and new[], but you're forced into that by Stroustrups' desire to maintain the core of C's semantics. Since you can't tell a pointer from an array, you have to tell the compiler yourself. You could fix that, but doing so would mean changing the semantics of the C part of the language radically; you could no longer make use of the identity
*(a+i) == a[i]
which would break a very large subset of all C code.
So, you could have a language which
implements a more complicated notion of an array, and eliminates the wonders of pointer arithmetic, implementing arrays with dope vectors or something similar.
is garbage collected, so you don't need your own delete discipline.
Which is to say, you could download Java. You could then extend that by changing the language so it
isn't strongly typed, so type checking the void * upcast is eliminated,
...but that means that you can write code that transforms a Foo into a Bar without the compiler seeing it. This would also enable ducktyping, if you want it.
The thing is, once you've done those things, you've got Python or Ruby with a C-ish syntax.
I've been writing C++ since Stroustrup sent out tapes of cfront 1.0; a lot of the history involved in C++ as it is now comes out of the desire to have an OO language that could fit into the C world. There were plenty of other, more satisfying, languages that came out around the same time, like Eiffel. C++ seems to have won. I suspect that it won because it could fit into the C world.
The rant, IMHO, is very misleading and it seems to me that the author does understand the finer details, it's just that he appears to want to mislead. IMHO, the key point that shows the flaw in argument is the following:
void* operator new(std::size_t size, void* ptr) throw();
The standard defines that the above function has the following properties:
Returns: ptr.
Notes: Intentionally performs no other action.
To restate that - this function intentionally performs no other action. This is very important, as it is the key to what placement new does: It is used to call the constructor for the object, and that's all it does. Notice explicitly that the size parameter is not even mentioned.
For those without time, to summarise my point: everything that 'malloc' does in C can be done in C++ using "::operator new". The only difference is that if you have non aggregate types, ie. types that need to have their destructors and constructors called, then you need to call those constructor and destructors. Such types do not explicitly exist in C, and so using the argument that "malloc does it better" is not valid. If you have a struct in 'C' that has a special "initializeMe" function which must be called with a corresponding "destroyMe" then all points made by the author apply equally to that struct as they do to a non-aggregate C++ struct.
Taking some of his points explicitly:
To implement multiple inheritance, the compiler must actually change the values of pointers during some casts. It can't know which value you eventually want when converting to a void * ... Thus, no ordinary function can perform the role of malloc in C++--there is no suitable return type.
This is not correct, again ::operator new performs the role of malloc:
class A1 { };
class A2 { };
class B : public A1, public A2 { };
void foo () {
void * v = ::operator new (sizeof (B));
B * b = new (v) B(); // Placement new calls the constructor for B.
delete v;
v = ::operator new (sizeof(int));
int * i = reinterpret_cast <int*> (v);
delete v'
}
As I mention above, we need placement new to call the constructor for B. In the case of 'i' we can cast from void* to int* without a problem, although again using placement new would improve type checking.
Another point he makes is about alignment requirements:
Memory returned by new char[...] will not necessarily meet the alignment requirements of a struct intlist.
The standard under 3.7.3.1/2 says:
The pointer returned shall be suitably aligned so that it can be converted to a
pointer of any complete object type and then used to access the object or array in the storage allocated (until
the storage is explicitly deallocated by a call to a corresponding deallocation function).
That to me appears pretty clear.
Under specialized allocators the author describes potential problems that you might have, eg. you need to use the allocator as an argument to any types which allocate memory themselves and the constructed objects will need to have their destructors called explicitly. Again, how is this different to passing the allocator object through to an "initalizeMe" call for a C struct?
Regarding calling the destructor, in C++ you can easily create a special kind of smart pointer, let's call it "placement_pointer" which we can define to call the destructor explicitly when it goes out of scope. As a result we could have:
template <typename T>
class placement_pointer {
// ...
~placement_pointer() {
if (*count == 0) {
m_b->~T();
}
}
// ...
T * m_b;
};
void
f ()
{
arena a;
// ...
foo *fp = new (a) foo; // must be destroyed
// ...
fp->~foo ();
placement_pointer<foo> pfp = new (a) foo; // automatically !!destructed!!
// ...
}
The last point I want to comment on is the following:
g++ comes with a "placement" operator new[] defined as follows:
inline void *
operator new[](size_t, void *place)
{
return place;
}
As noted above, not just implemented this way - but it is required to be so by the standard.
Let obj be a class with a destructor. Suppose you have sizeof (obj[10]) bytes of memory somewhere and would like to construct 10 objects of type obj at that location. (C++ defines sizeof (obj[10]) to be 10 * sizeof (obj).) Can you do so with this placement operator new[]? For example, the following code would seem to do so:
obj *
f ()
{
void *p = special_malloc (sizeof (obj[10]));
return new (p) obj[10]; // Serious trouble...
}
Unfortunately, this code is incorrect. In general, there is no guarantee that the size_t argument passed to operator new[] really corresponds to the size of the array being allocated.
But as he highlights by supplying the definition, the size argument is not used in the allocation function. The allocation function does nothing - and so the only affect of the above placement expression is to call the constructor for the 10 array elements as you would expect.
There are other issues with this code, but not the one the author listed.
Does anyone know how I can, in platform-independent C++ code prevent an object from being created on the heap? That is, for a class "Foo", I want to prevent users from doing this:
Foo *ptr = new Foo;
and only allow them to do this:
Foo myfooObject;
Does anyone have any ideas?
Cheers,
Nick's answer is a good starting point, but incomplete, as you actually need to overload:
private:
void* operator new(size_t); // standard new
void* operator new(size_t, void*); // placement new
void* operator new[](size_t); // array new
void* operator new[](size_t, void*); // placement array new
(Good coding practice would suggest you should also overload the delete and delete[] operators -- I would, but since they're not going to get called it isn't really necessary.)
Pauldoo is also correct that this doesn't survive aggregating on Foo, although it does survive inheriting from Foo. You could do some template meta-programming magic to HELP prevent this, but it would not be immune to "evil users" and thus is probably not worth the complication. Documentation of how it should be used, and code review to ensure it is used properly, are the only ~100% way.
You could overload new for Foo and make it private. This would mean that the compiler would moan... unless you're creating an instance of Foo on the heap from within Foo. To catch this case, you could simply not write Foo's new method and then the linker would moan about undefined symbols.
class Foo {
private:
void* operator new(size_t size);
};
PS. Yes, I know this can be circumvented easily. I'm really not recommending it - I think it's a bad idea - I was just answering the question! ;-)
I don't know how to do it reliably and in a portable way.. but..
If the object is on the stack then you might be able to assert within the constructor that the value of 'this' is always close to stack pointer. There's a good chance that the object will be on the stack if this is the case.
I believe that not all platforms implement their stacks in the same direction, so you might want to do a one-off test when the app starts to verify which way the stack grows.. Or do some fudge:
FooClass::FooClass() {
char dummy;
ptrdiff_t displacement = &dummy - reinterpret_cast<char*>(this);
if (displacement > 10000 || displacement < -10000) {
throw "Not on the stack - maybe..";
}
}
#Nick
This could be circumvented by creating a class that derives from or aggregates Foo. I think what I suggest (while not robust) would still work for derived and aggregating classes.
E.g:
struct MyStruct {
Foo m_foo;
};
MyStruct* p = new MyStruct();
Here I have created an instance of 'Foo' on the heap, bypassing Foo's hidden new operator.
Because debug headers can override the operator new signature, it is best to use the ... signatures as a complete remedy:
private:
void* operator new(size_t, ...) = delete;
void* operator new[](size_t, ...) = delete;
You could declare a function called "operator new" inside the Foo class which would block the access to the normal form of new.
Is this the kind of behaviour you want ?
You could declare it as an interface and control the implementation class more directly from your own code.
this can be prevented by making constructors private and providing a static member to create an object in the stack
Class Foo
{
private:
Foo();
Foo(Foo& );
public:
static Foo GenerateInstance() {
Foo a ; return a;
}
}
this will make creation of the object always in the stack.
Not sure if this offers any compile-time opportunities, but have you looked at overloading the 'new' operator for your class?