I need help in understanding when shall I use the following options
char *a = new char();
and
char *a = new char[sizeof(int)+1];
and how the respective memory freeing calls should be made?
Any time you use new T, you have to call delete on the resulting pointer afterwards.
Any time you use new T[n], you have to call delete[] on the resulting pointer afterwards.
And that's really all there is to it.
But note that you typically shouldn't use them at all.
If you need a string, don't allocate a char array. Just declare a std::string (without using new). If you need an array whose size is determined at runtime, don't allocate an array. Declare a std::vector (without using new).
The fist one allocates a single char. You delete it with:
delete a;
The second one allocates an array of chars. The length you have chosen is a little strange. You deallocate it with:
delete[] a;
Now... I hope you don't think you can put a stringified number in the second a (something like "123456", because you'll need many more bytes. Let's say at least 12 if an int is 32 bits. There is a funny formula to calculate the minimum length necessary. It's an approximation of the log10 https://stackoverflow.com/a/2338397/613130
To be clear, on my machine sizeof(int) == 4, but in an int I can put -2147483648 that is 10 digits plus the -, so 11 (plus the zero terminator)
None of the expressions you show make much sense.
Also, as a general rule, never use an explicit delete (leave that to smart pointers and collections), and try to avoid using any explicit new.
For simple strings with char elements, just use
std::string a;
This is an example of leaving the new-ing and delete-ing to a library class (which is strongly preferable), in this case std::string.
Include the <string> header to get a declaration of the std::string type.
char *a = new char();
This creates a pointer to a single initialized char.
char *a = new char;
Creates a pointer to a single uninitialized char.
char *a = new char[sizeof(int)+1];
Creates a dynamically allocated char array, of size sizeof(int)+1, i.e. an uninitialized c-string of size sizeof(int)+1. Probably 5 or 9, depending on sizeof(int).
char *a = new char[sizeof(int)+1]();
The same, but the string is initialized.
You need to explicitly free the memory with delete for a single char* and delete[] for the char array.
Another thing worth pointing out as well as the other answers is do not mix the two statements up - you should know whether you allocated a pointer or an array to char* c so that:
You call the correct delete/delete[] operator when cleaning up memory
You do not try accessing data beyond the pointer's scope.
For example, if you did:
// Create a pointer to a single char and set the value
char* c = new char();
*c = 'a';
// Access the pointer using array syntax
char tmp1 = c[0]; // Works, returns 'a'
char tmp2 = c[1]; // Illegal!
Because there are no safe-guards on pointers trying to access c[1] would do something, but in this context it will not return what you expect, it will most likely return memory stored after the char* c pointer or random memory.
Related
#include <iostream>
using namespace std;
int main()
{
char* MainBlock = new char[100];
char* SubBlock1 = new (MainBlock) char[20];
char* SubBlock2 = new (MainBlock) char [20];
cout << static_cast<void*>(SubBlock1) << " " << static_cast<void*>(SubBlock2);
}
Why do both the pointers in the code above have the same address? I expected SubBlock2 to be 20 bytes after SubBlock 1.
Does this mean I can allocate an endless number of pointers with placement new even though I only have 100 bytes?
How can I ensure that SubBlock6 will be a nullptr or out of bounds using placement new?
Why do both the pointers in the code above have the same address?
Placement new accepts the exact address where it will initialize the object being created. You pass the same address, you get the same address.
Does this mean I can allocate an endless number of pointers with placement new even though I only have 100 bytes?
No. Each placement new reuses the storage. You can of course reuse the storage infinitely many times, but you will only ever have the same 100 characters allocated at most.
How can I ensure that SubBlock6 will be a nullptr or out of bounds using placement new?
There is no way. The onset is on you to provide valid storage for placement new to create the objects. If you don't, the behavior is undefined.
And finally, you don't need to muck about with placement new.
char *SubBlock1 = MainBlock;
char *SubBlock2 = MainBlock + 20;
Partitions the buffer just fine. Just be sure to delete[] only the pointer value stored in MainBlock.
The (MainBlock) argument is a placement argument. You are in fact explicitly telling the program to allocate both SubBlock1 and SubBlock2 at the address of MainBlock.
Each new expression to get the address at which to construct the object calls the appropriate allocation function. Once the allocation is done and the address is returned from the allocation function, it attempts to construct the object exactly at the specified address.
Given char* SubBlock1 = new (MainBlock) char[20];, it calls the following allocation function:
void* operator new[]( std::size_t count, void* ptr );
Called by the standard array form placement new expression. The standard library implementation performs no action and returns ptr unmodified.
As the documentation above say, calling this allocation function does nothing and returns the address you passed unmodified. So, this new expression constructs 20 char exactly at MainBlock. This is why you get the same address for both SubBlock1 and SubBlock2.
Does this mean I can allocate an endless number of pointers with placement new even though I only have 100 bytes?
No. Note that allocation and construction are two different things. In your example, you allocate the memory only once and construct objects many times on it. So the layout of objects constructed on the allocated memory is up to you.
Sorry if this question will sound stupid, but I'm just starting to learn C++ and there is something confusing me about the placement new
I've been reading C++ Primer (which I find is a very good book to learn C++), and in the placement new section there is an example given. The example uses a char array to provide memory space for the placement new
const int BUF = 512;
const int N = 5;
char buffer[BUF];
double * pd1;
pd1 = new (buffer) double[N];
My question is why is it using a char array to provide memory space for the placement new? Also the last line in the code above is allocating memory for an array of double, how is that possible when the original memory space contains a char array? If the placement new is using the memory space of the char array, does this mean when we allocate the double array it overwrites the char array in that memory?
Again sorry if the question is strange, but hope I've made it quite clear.
why is it using a char array to provide memory space for the placement new?
Why not? char is the smallest type that C++ defines, and on virtually every implementation, it is one byte in size. Therefore, it makes a good type to use when you need to allocate a block of memory of a certain size.
C++ also has very specific mechanics about how arrays of char (and only char are allocated. A new char[*], for example, will not be aligned to the alignment of char. It will be aligned to the maximum normal alignment for any type. Thus, you could use it to allocate memory and then construct any type into that memory.
Also the last line in the code above is allocating memory for an array of double, how is that possible when the original memory space contains a char array?
It is not allocating anything. It is constructing an array, using the memory you have given it. That's what placement new does, it constructs an object in the memory provided.
If the placement new is using the memory space of the char array, does this mean when we allocate the double array it overwrites the char array in that memory?
Yes.
Yes, the char array and the double array would overlap, more specifically they would start at the same address in memory, i.e. (long)buffer and (long)pd1 would be the same. We can emphasize the overlap even more by making the byte sizes match (assuming sizeof(char) == 1):
const int N = 5;
char buffer[N * sizeof(double)];
double *pd1 = new (buffer) double[N];
Yes, if you modify the data pd1 points to, then the data buffer points to would also be modified. And the other way round as well. (See also the GCC flag -fstrict-aliasing to learn about how compiler optimizations work with such an overlap.)
There are no stupid questions.
It uses char probably because it makes you think about raw bytes (char is usually 1 byte long). The last line on the code is not allocating memory, it just places a double array over the mentioned buffer. If it was an object, it would also call the constructor. Yes, the char array gets overwritten.
Memory is memory. The machine doesn't care what type of data is stored there, that's up to the language to define and enforce. The answer to "why" is "because C++ is designed to let you."
char buffer[BUF]; is just some memory. There's no type information attached to the bytes composing buffer. Only the compiler knows, that this memory region is supposed to hold characters. You could use any type, even double:
double buffer[BUF];
double *pd1 = new (buffer) double[N];
I am initializing a char pointer with some random values, and when I am trying to delete it, I am unable to. Why is that?
Here is what I am doing:
int main()
{
char *s = new char[50]; /*
* I know there is no reason for
* using new if initializing, but
* in order to use delete we need
* to allocate using new.
*/
s = "Harry";
delete s;
return 0;
}
If you really want to practice with pointer, you need to fix your code. The main problem is you are trying to assign string literal( which is const char[6] in here) to pointer s then try to modify it by calling delete which invoke undefined behavior(UB).
char *s = new char[50];
strcpy(s, "Harry"); // don't assign string literal to it
// re-assign pointer to string literal,
// lost pre-allocated memory position and caused delete to fail
// it's UB to modify string literal
delete []s; // new[]/delete[], new/delete need to be called in pair.
Just use std::string instead.
#include <string>
std::string s("Harry"); // no worries
The problem is that after this assignment:
s = "Harry";
Then your s is no longer pointing to the memory you have allocated. It is pointing to a different array, or a const char[6] to be precise. The other array isn't dynamically allocated, and isn't on the heap. You can't delete variables that aren't on the heap.
In addition, by changing the s pointer to point at something else before the dynamically allocated memory has been freed, you introduce a memory leak.
To fix your code, either copy "Harry" into the s array by using strcpy, or use std::string instead.
You should never initialize a pointer with a string constant this way. It creates memory leaks which can be very dangerous.
When you allocated the memory using new, a 50 char memory was allocated in heap and its pointer is returned in s. when you were trying to initializing this value (wrong way) using s="Harry" , a new space is allocated in stack, initialized with this value and returned in s.
This memory allocated in stack cannot be deleted using delete call because it works only on heap.
Also, the memory initially allocated using new can no longer be accessed using s. Thus, you have a memory leak over here.
You can notice a different address in your pointer s after this wrong initialization by making small changes in your program:
#include <stdio.h>
int main()
{
char *s = new char[50];
printf("\n %u",s); // print address before init
s = "Harry";
printf("\n %u",s); // print address after init
// delete s; // cannot delete from stack
return 0;
}
Like others have already suggested, an array of character should be initialized using
strcpy(s, "Harry");
A char* is not actually a string. It is a pointer to some character with more characters to follow and ending with '\0'.
A character literal in C (and thus in C++) like "abc" is just an array of characters, with the compiler silently adding a '\0'. When you assign an array to a pointer, the array silently converts a pointer to the first element.
s = "Harry" means, the pointer s is assigned the address of the first character in the string literal "Harry". So the old value is lost and as this was the address of a dynamically allocated character array, leakage is supposed to happen.
std::strcpy, on the other hand, copies a string character by character from one array to another array. No pointers will be changed, only pieces of memory are copied. The pointer to the target array still points to the target array afterwards, only the data in that array has changed.
I don't think this occurs with initialized pointers.
When using a pointer, you can only delete (free) the memory it's pointing to, not the pointer itself, since it's an automatic object and will be deleted at the end of the block.
In many tutorials, the first code samples about dynamic memory start along the lines of:
int * pointer;
pointer = new int; // version 1
//OR
pointer = new int [20]; // version 2
They always proceed to explain how the second version works, but totally avoid talking about the first version.
What I want to know is, what does pointer = new int create? What can I do with it? What does it mean? Every tutorial without fail will avoid talking about the first version entirely. All I've found out (through messing about) is this:
#include <iostream>
using namespace std;
int main()
{
int * pointer;
pointer = new int;
pointer[2] = 1932; // pointer [2] exists? and i can assign to it?!
cout << pointer[2] << endl; // ... and access it successfully?!
};
The fact that I can subscript pointer tells me so far that pointer = new int implicitly creates an array. But if so, then what size is it?
If someone could help clear this all up for me, I'd be grateful...
My teacher explained it like this.
Think of cinema. The actual seats are memory allocations and the ticket you get are the pointers.
int * pointer = new int;
This would be a cinema with one seat, and pointer would be the ticket to that seat
pointer = new int [20]
This would be a cinema with 20 seats and pointer would be the ticket to the first seat. pointer[1] would be the ticket to the second seat and pointer[19] would be the ticket to the last seat.
When you do int* pointer = new int; and then access pointer[2] you're letting someone sit in the aisle, meaning undefined behaviour
This is a typical error in C and C++ for beginners. The first sentence, creates a space for holding just an int. The second one creates a space for holding 20 of those ints. In both cases, however, it assigns the address of the beginning of the dynamically-reserved area to the pointer variable.
To add to the confusion, you can access pointers with indices (as you put pointer[2]) even when the memory they're pointing is not valid. In the case of:
int* pointer = new int;
you can access pointer[2], but you'd have an undefined behavior. Note that you have to check that these accesses don't actually occur, and the compiler can do usually little in preventing this type of errors.
This creates only one integer.
pointer = new int; // version 1
This creates 20 integers.
pointer = new int [20] // version 2
The below is invalid, since pointer[2] translates as *(pointer + 2) ; which is not been created/allocated.
int main()
{
int * pointer;
pointer = new int;
pointer[2] = 1932; // pointer [2] exists? and i can assign to it?!
cout << pointer[2] << endl; // ... and access it succesfuly?!
};
Cheers!
new int[20] allocates memory for an integer array of size 20, and returns a pointer to it.
new int simply allocates memory for one integer, and returns a pointer to it. Implicitly, that is the same as new int[1].
You can dereference (i.e. use *p) on both pointers, but you should only use p[i] on the pointer returned by the new int[20].
p[0] will still work on both, but you might mess up and put a wrong index by accident.
Update: Another difference is that you must use delete[] for the array, and delete for the integer.
pointer = new int allocates enough memory on the heap to store one int.
pointer = new int [20] allocates memory to store 20 ints.
Both calls return a pointer to the newly allocated memory.
Note: Do not rely on the allocated memory being initialized, it may contain random values.
pointer = new int; allocates an integer and stores it's address in pointer. pointer[2] is a synonym for pointer + 2. To understand it, read about pointer arithmetic. This line is actually undefined behavior, because you are accessing memory that you did not previously allocate, and it works because you got lucky.
int* p = new int allocates memory for one integer. It does not implictly create an array. The way you are accessing the pointer using p[2] will cause the undefined behavior as you are writing to an invalid memory location. You can create an array only if you use new[] syntax. In such a case you need to release the memory using delete[]. If you have allocated memory using new then it means you are creating a single object and you need to release the memory using delete.
*"The fact that i can subscript pointer tells me so far that I pointer = new int implicitly creates an array. but if so, then what size is it?"
*
This was the part of the question which I liked the most and which you emphasize upon.
As we all know dynamic memory allocation makes use of the space on the Stack which is specific to the given program.
When we take a closer look onto the definition of new operator :-
void* operator new[] (std::size_t size) throw (std::bad_alloc);
This actually represents an array of objects of that particular size and if this is successful, then it automatically Constructs each of the Objects in the array. Thus we are free to use the objects within the bound of the size because it has already been initialized/constructed.
int * pointer = new int;
On the other hand for the above example there's every possibility of an undefined behaviour when any of
*(pointer + k) or *(k + pointer)
are used. Though the particular memory location can be accessed with the use of pointers, there's no guarantee because the particular Object for the same was not created nor constructed.This can be thought of as a space which was not allocated on the Stack for the particular program.
Hope this helps.
It does not create array. It creates a single integer and returns the pointer to that integer. When you write pointer[2] you refer to a memory which you have not allocated. You need to be carefull and not to do this. That memory can be edited from the external program which you, I belive, don't want.
int * pointer; pointer = new int; // version 1
//OR
pointer = new int [20] // version 2
what I want to know is, what does pointer = new int create? what can I do with it? what does it mean? Every tutorial without fail will avoid talking about the first version entirely
The reason the tutorial doesn't rell you what to do with it is that it really is totally useless! It allocates a single int and gives you a pointer to that.
The problem is that if you want an int, why don't you just declare one?
int i;
So I have a couple of structs...
struct myBaseStruct
{
};
struct myDerivedStruct : public myBaseStruct
{
int a, b, c, d;
unsigned char* ident;
};
myDerivedStruct* pNewStruct;
...and I want to dynamically allocate enough space so that I can 'memcpy' in some data, including a zero-terminated string. The size of the base struct is apparently '1' (I assume because it can't be zero) and the size of the derived is 20, which seems to make sense (5 x 4).
So, I have a data buffer which is a size of 29, the first 16 bytes being the ints and the remaining 13 being the string.
How can I allocate enough memory for pNewStruct so that there is enough for the string? Ideally, I just want to go:
allocate 29 bytes at pNewStruct;
memcpy from buffer into pNewStruct;
Thanks,
You go back to C or abandon these ideas and actually use C++ as it's intended.
Use the constructor to allocate memory and destructor to delete it.
Don't let some other code write into your memory space, create a function that will ensure memory is allocated.
Use a std:string or std::vector to hold the data rather than rolling your own container class.
Ideally you should just say:
myDerivedClass* foo = new myDerivedClass(a, b, c, d, ident);
In the current C++ standard, myDerivedStruct is non-POD, because it has a base class. The result of memcpying anything into it is undefined.
I've heard that C++0x will relax the rules, so that more classes are POD than in C++98, but I haven't looked into it. Also, I doubt that very many compilers would lay out your class in a way that's incompatible with PODs. I expect you'd only have trouble with something that didn't do the empty base class optimisation. But there it is.
If it was POD, or if you're willing to take your chances with your implementation, then you could use malloc(sizeof(myStruct)+13) or new char[sizeof(myStruct)+13] to allocate enough space, basically the same as you would in C. The motivation presumably is to avoid the memory and time overhead of just putting a std::string member in your class, but at the cost of having to write the code for the manual memory management.
You can overallocate for any class instance, but it implies a certain amount of management overhead. The only valid way to do this is by using a custom memory allocation call. Without changing the class definition, you can do this.
void* pMem = ::operator new(sizeof(myDerivedStruct) + n);
myDerivedStruct* pObject = new (pMem) myDerivedStruct;
Assuming that you don't overload operator delete in the hierarchy then delete pObject will be a correct way to destroy pObject and deallocate the allocated memory. Of course, if you allocate any objects in the excess memory area then you must correctly free them before deallocating the memory.
You then have access to n bytes of raw memory at this address: void* p = pObject + 1. You can memcpy data to and from this area as you like. You can assign to the object itself and shouldn't need to memcpy its data.
You can also provide a custom memory allocator in the class itself that takes an extra size_t describing the amount of excess memory to allocate enabling you to do the allocation in a single new expression, but this requires more overhead in the class design.
myDerivedStruct* pObject = new (n) myDerivedStruct;
and
struct myDerivedStruct
{
// ...
void* operator new(std::size_t objsize, std::size_t excess storage);
// other operator new and delete overrides to make sure that you have no memory leaks
};
You can allocate any size you want with malloc:
myDerivedStruct* pNewStruct = (myDerivedStruct*) malloc(
sizeof(myDerivedStruct) + sizeof_extra data);
You have a different problem though, in that myDerivedStruct::ident is a very ambigous construct. It is a pointer to a char (array), then the structs ends with the address where the char array starts? ident can point to anywhere and is very ambigous who owns the array ident points to. It seems to me that you expect the struct to end with the actual char array itself and the struct owns the extra array. Such structures usualy have a size member to keep track of teir own size so that API functions can properly manage them and copy them, and the extra data starts, by convention, after the structure ends. Or they end with a 0 length array char ident[0] although that creates problems with some compilers. For many reasons, there is no place for inheritance in such structs:
struct myStruct
{
size_t size;
int a, b, c, d;
char ident[0];
};
Mixing memcpy and new seems like a terrible idea in this context. Consider using malloc instead.
You can dynamically allocate space by doing:
myDerivedStruct* pNewStruct = reinterpret_cast<myDerivedStruct*>(new char[size]);
however
Are you sure you want to do this?
Also, note that if you are intending to use ident as the pointer to the start of your string, that would be incorrect. You infact need &ident, since the ident variable is itself at the start of your unused space, interpreting what is at that space as a pointer is most likely going to be meaningless. Hence, it would make more sense if ident were unsigned char or char rather than unsigned char*.
[edit again]
I'd just like to emphasise that what you're doing is really a really really bad idea.
char* buffer = [some data here];
myDerivedStruct* pNewStruct = new myDerivedStruct();
memcpy(buffer,pNewStruct,4*sizeof(int));
pNewStruct->ident = new char[ strlen(buffer+(4*sizeof int)) ];
strcpy(pNewStruct->ident,buffer+(4*sizeof int));
Something like that.
Is the buffer size known at compile time? A statically allocated array would be an easier solution in that case. Otherwise, see Remus Rusanu's answer above. That's how the win32 api manages variable sized structs.
struct myDerivedStruct : public myBaseStruct
{
int a, b, c, d;
unsigned char ident[BUFFER_SIZE];
};
Firstly, I don't get what's the point of having a myBaseStruct base. You proivided no explanation.
Secondly, what you declared in your original post will no work with the data layout you described. For what you described in the OP, you need the last member of the struct to be an array, not a pointer
struct myDerivedStruct : public myBaseStruct {
int a, b, c, d;
unsigned char ident[1];
};
Array size doesn't matter, but it should be greater than 0. Arrays of size 0 are explicitly illegal in C++.
Thirdly, if you for some reason want to use new specifically, you'll have to allocate a buffer of char objects of required size and then convert the resultant pointer to your pointer type
char *raw_buffer = new char[29];
myDerivedStruct* pNewStruct = reinterpret_cast<myDerivedStruct*>(raw_buffer);
After that you can do your memcpy, assuming that the size is right.