What is the second line? (Seen while answering another question.)
int * x = new int [1] ;
int * y = new (x) int;
After the second line x and y have the same value (point to a same place). What's the difference between y = x and the second line? Is it like a constructor or something?
It's placement new. It constructs a new int in the memory pointed to by x.
If you try:
int * x = new int [1];
*x = 5;
std::cout << *x << std::endl;
int * y = new (x) int;
*y = 7;
std::cout << *x << std::endl;
the output will be:
5
7
This is called placement new. It allows you to construct an object in memory already allocated.
This earlier thread discusses where and how it is useful for.
The second new is a "placement new". It performs initialization (i.e. call any necessary constructors) without doing any allocation. It is useful when you need to create a custom memory allocation scheme.
This is placement new.
Though you don;t usually use it with integer types.
It is usually used to build a buffer where you then build other types into.
// Allocate a buffer with enough room for two T objects.
char* buffer = new char[sizeof(T) * 2];
// Allocate a T in slot zero
T* t1 = new (buffer + 0 * sizeof(T)) T("Zero");
// Allocate a T in slot one
T* t2 = new (buffer + 1 * sizeof(T)) T("One");
Thats the basics.
But remember that the objects allocated with placement new can not be deleted with the delete statement. This is because delete tries to reclaim memory allocated by new (as well as call the destructor). So to use these objects correctly you must manually call there destructor.
t1->~T();
t2->~T();
Don't forget to delete the original buffer.
delete [] buffer;
A few other caveats:
People often see that buffer could be implemented on the stack and thus be automatically freed
char buffer[sizeof(T) * 2];
Unfortunately this may be technically OK (It compiles). But it is not guaranteed to work as the memory of buffer may not be aligned correctly for a T to be placed inside. So you must allocate the buffer dynamically (by using new it gurantees that the memory is aligned correctly for any object of the size allocated (thus by extension it is also aligned for any size smaller then the size allocated). The easy way to get around this problem is to use a std::vector
std::vector<char> buffer(sizeof(T) * 2);
T* t1 = new (&buffer[0] + 0 * sizeof(T)) T("Zero");
T* t2 = new (&buffer[0] + 1 * sizeof(T)) T("One");
Another use of placement new is to reset an object.
I have seen this done but I prefer to use the more standard assignment operator:
T obj1("Plop");
obj1 = T("Another Plop");
// Can be done like this:
T obj1("Plop");
obj1.~T();
new (&obj1) T("Another Plop"); // Seems excessive to me. But can be us-full
// in some extreme situations.
Remember if you use the reset method you must destroy the old object first (or the object may not behave correctly).
int * y = new (x) int;
This is as per placement new syntax.
EDIT: Along with custom allocation, placement new also helps to re-initialze an object state like below.
class Test
{
int startVal;
public:
Test()
{
startVal = 1;
}
void setVal(int val) { startVal = val; }
};
int main()
{
Test *p = new Test; //Creates new object and initializes it with
//a call to constructor.
p->setVal(10); //Change object content.
new(p) Test; //Reset object:
//object pointed by p will be re-initialzed here by making
//a call to constructor. startVal will be back to 1
}
As described in comments above, object state resetting also can be achieved using placement new.
placement new doesn't allocate memory, it constructs object at the specified address in the paranthesis.
Related
I'm experimenting the usage of placement new to try to understand how it works.
Executing the code below:
#include <iostream>
#define SHOW(x) std::cout << #x ": " << x << '\n'
template<typename T>
static T *my_realloc(T *ptr, size_t count) {
return (T *) realloc((void *) ptr, count * sizeof(T));
}
template<typename T>
static void my_free(T *ptr) {
free((T *) ptr);
}
int main() {
constexpr int count = 40;
int cap = 0;
int size = 0;
std::string *strs = nullptr;
auto tmp_str = std::string();
for(int i = 0; i < count; i++) {
tmp_str = std::to_string(i);
if(size == cap) {
if(cap == 0)
cap = 1;
else
cap *= 2;
strs = my_realloc(strs, cap);
}
new (&strs[size++]) std::string(std::move(tmp_str));
}
for(int i = 0; i < size; i++)
SHOW(strs[i]);
std::destroy_n(strs, size);
my_free(strs);
return 0;
}
I get the errors:
Invalid read of size 1
Invalid free() / delete / delete[] / realloc()
Removing the line
std::destroy_n(strs, size);
The error of invalid free is solved, but somehow all memory of the program is freed and no leaks are generated. But i can't find how the std::string destructor is called in the program.
If you want to store non-trivial types (such as std::string), then realloc simply cannot be used. You will find that standard library containers like e.g. std::vector will also not use it.
realloc may either extend the current allocation, without moving it in memory, or it might internally make a new allocation in separate memory and copy the contents of the old allocation to the new one. This step is performed as if by std::memcpy. The problem here is that std::memcpy will only work to actually create new objects implicitly in the new allocation and copy the values correctly if the type is trivially-copyable and if it and all of its subobjects are implicit-lifetime types. This definitively doesn't apply to std::string or any other type that manages some (memory) resource.
You are also forgetting to check the return value of realloc. If allocation failed, it may return a null pointer, which you will then use regardless, causing a null pointer dereference, as well as a memory leak of the old allocation.
Instead of using realloc you should make a new allocation for the new size, then placement-new copies of the objects already in the old allocation into the new one and then destroy the objects in the old allocation and free it.
If you want to guarantee that there won't be memory leaks when exceptions are thrown things become somewhat complicated. I suggest you look at the std::vector implementation of one of the standard library implementations if you want to figure out the details.
strs = my_realloc(strs, cap);
strs is a pointer to a std::string, and this will result in the contents of the pointer to be realloc()ed.
This is undefined behavior. C++ objects cannot be malloced, realloced, or freeed. Using a wrapper function, or placement new, at some point along the way, does not change that.
Everything from this point on is undefined behavior, and the resulting consequences are of no importance.
What is the difference between these pointers?
I know that this one is going to be stored on the heap, even though a pointer is only 8 bytes anyways, so the memory is not important for me.
int* aa = new int;
aa = nullptr;
and this one is going to be stored on the stack.
int* bb = nullptr;
They both seem to work the same in my program. Is there any difference apart from memory allocation? I have a feeling that the second one is bad for some reason.
2) Another question which is somewhat related:
Does creating a pointer like that actually take more memory? If we take a look at the first snippet, it creates an int somewhere (4 bytes) and then creates a pointer to it (8 bytes), so is it 12 bytes in total? If yes are they both in the heap then? I can do this, so it means an int exists:
*aa = 20;
Pointers are integers that just indicate a memory position, and a type (so they can only point to variables of that type).
So in your examples, all pointers are stored in the stack (unless they are global variables, but that is another question). What they are pointing to is in the heap, as in the next example.
void foo()
{
int * ptr = new int(42);
// more things...
delete ptr;
}
You can have a pointer pointing into the stack, for example, this way:
void foo()
{
int x = 5;
int * ptr = &x;
// more things...
}
The '&' operator obtains the memory position of the variable x in the example above.
nullptr is the typed equivalent to old NULL. They are a way to initialize a pointer to a known and secure value, meaning that they are not pointing to anything else, and that you can compare whether they are NULL or not.
The program will accept pointers pointing to the stack or the heap: it does not matter.
void addFive(int * x)
{
*x += 5;
}
void foo()
{
int x = 5;
int * ptr1 = &x;
int * ptr2 = new int(42);
addFive( ptr1 );
addFive( ptr2 );
addFive( &x );
printf( "%d\n", *ptr1 );
printf( "%d\n", *ptr2 );
// more things...
delete ptr2;
}
The only difference is that the C runtime will keep structures telling how much memory has been spent in the heap, and therefore storing variables in the heap comes at a cost in performance. On the other hand, the stack is always limited to a fixed amount of memory (relatively small), while the heap is much larger, allowing you to store big arrays, for example.
You could take a look at C-Sim, which simulates memory in C (disclaimer: I wrote it).
Hope this helps.
If I have this two vectors of pointers to MyClass
vector<MyClass*> A;
vector<MyClass*> B;
where A is full and B is empty and I do this operation:
B = A;
Have I to delete the pointers of both vectors or just one?
If I have a dynamic object like this:
MyClass *p = new MyClass;
And this pointer:
MyClass *p2;
If I do this operation:
p2 = p1;
Have I to delete both p and p2 or just one of two?
The pointers are pointing to the same piece of memory, so you only need to delete it once.
You get undefined behaviour if you try to delete an object through a pointer more than once.
A pointer is just(*1) a regular variable containing an unsigned integer value. This value is an address in memory where the pointed-to-value is stored.
In simpler terms, you can think of a pointer as an array index to memory.
byte ram[16 * 1024 * 1024 * 1024]; // 16Gbs of memory.
size_t index = 10000; // indexes the 10,000th byte of ram.
byte* ptr = ram+ 10000; // ptr contains the same actual value as index
ptr = &ram[10000]; // same value again
ptr = ram;
ptr += 10000; // same value again
When you declare the variable as a pointer, you are extending it's contract within the language. Although, underneath, it is still just a regular variable, the language will treat your interactions with it differently because it is aware that you are expecting to use it to reference memory like this.
So, to answer your original question: You need to match every alloc with a single, corresponding delete. This is a concept called "ownership".
char* a = new char[64];
char* b = a;
Both a and b contain the same value, the address of our 64 bytes, but only one of them "owns" the allocation.
That determination is up to the programmer, and is deterministic: Which pointer will last longest? Which will try to use the pointer last?
char* a = new char[64];
if (a != nullptr)
{
char* b = a;
strcpy(b, "hello world");
// <-- end of b's lifetime.
}
std::cout << a << '\n';
If we deleted b at the end of it's lifetime, a would still point to it. The actual underlying memory is untouched, the problem is that the memory could be allocated to someone else in the mean time. (You forget your watch in the drawer of a hotel. If you go back a week after your stay, will your watch still be in the top drawer?)
In the above example, clearly a is more authoritative for the allocation, so we should delete after a has finished using it.
char* a = new char[64];
if (a != nullptr)
{
char* b = a;
strcpy(b, "hello world");
// <-- end of b's lifetime.
}
std::cout << a << '\n';
delete [] a; // we used new [] match with delete []
Pointer management can easily be difficult, and has been causing bugs in C code since C existed.
C++ provides several classes that encapsulate the properties of ownership. std::unique_ptr is a single point of ownership for allocations ideal for when you have a container of pointers.
std::vector<std::unique_ptr<YourClass>> myVector;
myVector.emplace_back(new YourClass));
when this vector goes out of scope, the unique_ptr objects will go out of scope, at which point they will delete their allocations. Problem solved.
There is also std::shared_ptr if you may need the ownership to be dynamic...
std::vector<std::shared_ptr<MailItem>> inbox;
std::set<std::shared_ptr<MailItem>> urgent;
// incoming mail goes into inbox, copied to urgent if its a priority...
for (auto it : inbox)
{
if (it->>IsPriority()) {
urgent.insert(it);
// now there are TWO pointers to the same item.
}
}
In the above case, the user can delete an urgent item from inbox but the item still exists. shared_ptr uses a "reference counter" to know how many pointers own the object. In most cases, this is going to be more complex than you need and unique_ptr will be sufficient.
(*1 There are some platforms where pointers are more than just a single variable but that's kind of advanced and you probably don't need to worry about that until such time as you work on such a platform)
I have the following pointer:
jfloat *verticesLocal;
And I want make a new copy to:
jfloat *vertices;
I want to copy the values from verticesLocal to vertices.
How can I do that? I've just tried the following command, but it doesn't work:
memcpy(vertices, verticesLocal, numVerticesLocal * sizeof(jfloat));
I can't see the error because I'm working with Android native code. Sorry.
The idea of "copying a pointer", when taken literally, is nothing more than a simple assignment.
int x = 5;
int* p1 = &x;
int* p2 = p1; // there, we copied the pointer.
In this case, both p1 and p2 point to the same data - the int variable x. However, because this is so trivial, I'm inclined to think that what you really are asking about is how to copy the data that the pointer points to.
In this case, it depends on the data type. If the pointer points to a simple buffer of PODs, this involves allocating a separate buffer, and then using something like memcpy (or preferably std::copy) to copy the data. For example:
int* p1 = new int[100];
// ... fill p1 with values
int* p2 = new int[100]; // create a new buffer
std::copy(p1, p1 + 100, p2); // copy the data into p2
Or, you can use memcpy to copy the buffer byte-by-byte, since the buffer contains PODs.
memcpy(p2, p1, 100 * sizeof(int));
However, if the pointed-to data is not a simple buffer, but rather a C++ object, you can't use memcpy. You need to perform a deep copy of the object, (usually using the object's copy constructor) to get a clone of the object. How this is done, or whether it's even possible, depends on the object. (Some objects are noncopyable.)
I have no clue what a jfloat is, but if the object is, for example, an std::string, you would just do something like:
std::string* s1; // assume this points to a valid string
std::string* s2 = new std::string();
*s2 = *s1; // copies s1 using s2's assignment operator
In this contrived example it would be preferable to avoid heap-allocation altogether, and just use stack variables. But it demonstrates the idea of copying a heap-allocated object.
malloc first, then do your memcpy.
If you are copying the pointer, it is a simple assignment:
jfloat* verticesLocal; // assuming is is allocated already
jfloat* newVertices = verticesLocal;
IF you mean you want to copy the data the point points to, you have to allocate the memory for the new block of memory first:
// assume jfloat* verticesLocal is pointing to a valid memory block of size i
jfloat* newVertices = new jfloat[i];
memcpy(newVertices, verticesLocal, i * sizeof(jfloat));
this is how you copy an array buffer :
unsigned char *pBufferSrc = new unsigned char[10];
unsigned char *pBufCpd = new unsigned char[10];
for (int i = 0; i < 10; i++)
pBufferSrc[i] = i; // pBufferSrc = [0,1,2,3,4,5,6,7,8,9]
memcpy(pBufCpd, pBufferSrc, 10); // data from pBufferSrc is copied to pBufCpd (0,1,2,..9)
delete []pBufferSrc; // if even pBufferSrc buffer gets deleted, pBufCpd still has the data
I am declaring an array of void pointers. Each of which points to a value of arbitary type.
void **values; // Array of void pointers to each value of arbitary type
Initializing values as follows:
values = (void**)calloc(3,sizeof(void*));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;
//Trying to Clear the memory allocated
free(*values);
//Error: *** glibc detected *** simpleSQL: free(): invalid pointer: 0x080611b4
//Core dumped
delete[] values*;
//warning: deleting 'void*' is undefined
//Similar Error.
Now how do I free/delete the memory allocated for values ( the array of void pointers)?
I suspect the issue is with the way that you allocated values: values = (void*)calloc(3,sizeof(void)). That should be sizeof(void *) rather than just sizeof(void).
sizeof(void) may be zero or something else that makes no sense, so you're not really allocating any memory to begin with... it's just dumb luck that the assignments work, and then the error pops up when you try to deallocate the memory.
EDIT: You're also asking for trouble by alternating between C++-style new/delete with C-style malloc/free. It is okay to use them both as long as you don't delete something you malloc'ed or free something you new'ed, but you're going to mix them up in your head if you go like this.
You have 3 things that are dynamically allocated that need to be freed in 2 different ways:
delete reinterpret_cast<int*>( values[0]);
delete reinterpret_cast<float*>( values[1]);
free( values); // I'm not sure why this would have failed in your example,
// but it would have leaked the 2 items that you allocated
// with new
Note that since str is not dynamically allocated it should not (actually cannot) be freed.
A couple of notes:
I'm assuming that the sizeof(void)
was meant to be sizeof(void*)
since what you have won't compile
I'm not going to say anything about
your seemingly random casting except
that it looks like code that ready
for disaster in general
This is the perfect situation for the boost::any class
Also you may want to consider using a vector rather than allocating your own memory.
std::vector<boost::any> data;
boost::any i1 = 1; // add integer
data.push_back(i1);
boost::any f1 = 1.0; // add double
data.push_back(f1);
data.push_back("PLOP"); // add a char *
std:: cout << boost::any_cast<int>(data[0]) + boost::any_cast<double>(data[1])
<< std::endl;
Going back to your original code the main problem was:
values = (void*)calloc(3,sizeof(void));
// This should have been
void** values = (void**)calloc(3,sizeof(void*));
// Freeing the members needs care as you need to cast them
// back to the correct type before you release the memory.
// now you can free the array with
free(values);
Also note: Though it is not illegal to use both new/delete and calloc/free in the same piece of code it is frowned upon. Mainly because it is easy to get things mixed up and that could potentially be fatal.
You're mixing new and *alloc(). That's a no-no, and can lead to undefined results.
I'm not sure why you are using new if you're doing things in C (referencing the tag here).
I would malloc the individual pieces of the array I need and then free them when I'm done I suppose. You can't free something you didn't first malloc. You also can't delete a void pointer.
Note that you're also not deleting values[0] and values[1] which is a memory leak, Yet by your design you can't free values[2] since its a pointer into you .data section.
You'd have to keep track of how many void* were originally calloc'd, and iterate over them, free-ing each one, then free the original values variable.
darn formatting... (the preview is working fine).
int ct = 3;
values = (void*)calloc(ct,sizeof(void));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;
for ( int i = 0; i < ct; i++ ) [
delete( values[i] );
}
free( values );