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
Related
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 had one question.
I developing server in ASIO and packets are in pointed char.
When i create new char (ex. char * buffer = new char[128];) i must clean it manually to nulls.
By:
for(int i =0;i<128;i++)
{
buffer[i] = 0x00;
}
I doing something wrong, that char isn't clear ?
You do not have to loop over an array of un-initialized values. You can dynamically instantiate array of zeros like this:
char * buffer = new char[128](); // all elements set to 0
^^
There are two types of ways of calling the new operator in C++ - default initialised and zero initialised.
To default initialise (which will leave the value undefined) call:
int * i = new int;
It is then undefined behavoir to read or use this value until its been set.
To zeroinitialise (which will set to 0) use:
int * i = new int();
This also works with arrays:
int * i = new int[4]; // ints are not initialised, you must write to them before reading them
int * i = new int[4](); // ints all zero initialised
There's some more info here
Allocated memory will not be clear, it will contain random stuff instead. That's how memory allocation works. You have to either run a for-loop or use memset to clear it manually.
You also can use calloc. It initializes each elem to 0 automaticaly.
e.g:
char* buffer = (char *) calloc (128, sizeof (char))
First param is number of blocks to be allocated. Second is size of block.
This function returns void* so you have to convert its value to (char *)
If you use calloc (or malloc or any "pure c" allocation functions) you'd better use free function to deallocate memory instead of delete.
First off, I apologize if this has been asked before. I can't seem to find the right info.
The following code does not print "300" as I thought it would:
#include <iostream>
int main()
{
int *array;
int *arrayCopy = array;
array = new int[4];
array[0] = 100;
array[1] = 200;
array[2] = 300;
array[3] = 400;
std::cout << arrayCopy[2];
return 0;
}
However, it does, if I move the line
int *arrayCopy = array;
below the line that follows it in the above code. Why is that?
(PS: I know there is a memory leak, and that std::vector is better... I'm just curious).
No, when you do int *arrayCopy = array; you capture the value of array into arrayCopy at that moment of time, so if you modify (note that initially array is pointing to some random location, you make it point to a correct location by doing new) the array after you copied to the arrayCopy then those changed will not be reflected back to arrayCopy.
Maybe you're thinking of using a reference to a pointer? Here's what happens with your current code:
int *array; // Currently points to an undefined (invalid) memory location.
int *arrayCopy = array; // Now this points to the same undefined memory location as array.
array = new int[4]; // Now array points to valid memory, but arrayCopy still points to undefined space.
If you did something like this though, it's different:
int *array; // Points to undefined
int *&arrayCopy = array; // This is a reference to array. That means if you change array, arrayCopy will also reflect the changes.
array = new int[4]; // Now since array points to valid space, arrayCopy does too.
Technically, this isn't entirely true because different things are happening. A reference is essentially the same level of indirection as a pointer, except the compiler does all the dereferencing for you. But what I described is essentially how it works. If you just stick the extra & in there, your code will do what you were thinking.
int *array; // array is ???
int *arrayCopy = array; // copy is ???
array = new int[4]; // array is valid pointer, copy still ???
This code snippet does the following:
creates an int pointer of indeterminate value (could be anything).
copies that indeterminate value to the copy.
changes the value of the original pointer to point to a newly created array.
In other words, the third line "disconnects" the two pointers, leaving the copy still pointing to an indeterminate location.
Dereferencing that pointer copy is undefined behaviour, not something you want to muck about with.
In contrast, if the sequence is changed to (as mentioned in your question):
int *array; // array is ???
array = new int[4]; // array is valid pointer
int *arrayCopy = array; // copy is now also the valid pointer
then the copy pointer is set to the original after the original has been initialised to point to the array. No disconnect occurs, so that array[2] is effectively the same as arrayCopy[2].
Is it possible to copy a dynamically allocated array pointer prior to memory allocation?
No.
However, you can do this:
int *array;
int *&arrayReference = array;
int *array; // points to some random value
int *arrayCopy = array; // points to the same value
array = new int[4]; // array points to a new value, arrayCopy does not
If you want to make a pointer that points to whatever "array" points to at all time, create a double pointer
http://computer.howstuffworks.com/c32.htm
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.
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 );