delete[] Array of characters [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
delete[] supplied a modified new-ed pointer. Undefined Behaviour?
Let's say I've allocated a handful of characters using new char[number].
Will it be possible to delete only a few end characters (something like delete[] (charArray + 4);, which will supposedly de-allocate all of characters except for the first four)?
I read that some implementations' new[] store the number of objects allocated before the array of objects so that delete[] knows how many objects to de-allocate, so it's probably unsafe to do what I'm asking...
Thanks.
EDIT:
Is manually deleting the unwanted end bytes using separate delete statements a safe way to do what I'm asking?

No, you have to delete[] exactly the same pointer you get back with new[].

You can't delete a specific segment of an array.
If you're just operating on C strings, you can set a character to \0 and any functions that operate on the string will stop there, as C strings are null-terminated.
If you actually need to free up that memory, the closest you can get would be to make a new, smaller array, copy the elements over, and delete[] the old array.
char* TenCharactersLong = new char[10];
// ...
char* FirstFiveCharacters = new char[5];
for (std::size_t Index = 0; Index < 5; Index++)
{
FirstFiveCharacters[Index] = TenCharactersLong[Index];
}
delete[] TenCharactersLong;

The only "safe" way to do it is to allocate a new array, copy the data, and delete the old one. Or you could just follow the std::vector way and differentiate between "capacity" (the size of the array) and "size" (the amount of elements in it).

Nope, sorry. Memory allocation is complex enough with fragmentation, alignment, padding, overheads, whatnot. A feature like this would only further amplify these problems.
Is manually deleting the unwanted end bytes using separate delete statements a safe way to do what I'm asking?
Don't even try. This can be dangerous. Always deallocate arrays with delete [].
I highly recommend reading the C++ FAQ Lite on this topic: 16.13, 16.14

No, you can only delete the entire array.

No, you can't do that. I'd suggest using an std::vector for this. This way you can pinpoint the indexes that you want to remove and just let the libraries handle it for you.

Related

Playing with char array

Is that safe to do something like this:
char* charArray = new char[10];
strcat(charArray, "qwertyuiop");
charArray[3] = '\0';
delete [] charArray;
Will everything be deleted? Or that what is after \0 won't be? I don't know if I'm leaving garbage.
EDIT: should be strcpy
Apart from the fact that new[] for POD-types does not zero-initializes the array, and strcat would write the terminating '\0' past the end of the allocated area, everything looks fine: in particular, delete will delete the entire block.
The reason for writing past the end of the allocated block is that the 10-character string "qwertyuiop" requires 11 bytes to store.
If you wanted to write strcpy instead of strcat, then that is safe and correct. But it seems you've a misconception about delete [] charArray. It doesn't delete characters, it deletes the memory pointed to by charArray. The memory even after delete [] charArray might contain those characters, it is not guaranteed though.
However, if you really wanted to write strcat, and it is not a typo, then your code invokes undefined behavior, because charArray contains garbage to which strcat will attempt to concatenate the second string.
The delete[] releases the memory allocated after destroying the objects within (which diesn't do anything for char). It doesn't care about the content i.e. it will deallocate as many objects as were allocated.
Note that the use of strcat() depends on a null character to find the end of the string and that the memory returned from new char[n] is uninitialized. You want to start of with
*charArray = 0;
... and you might want to consider strncat() or, yet better, not use this at all but rather use std::string.
The delete[] statement does not know anything about what is stored in the buffer (including whether it is a string or not), so it will delete all 10 characters. However, your strcat call is overflowing the end of the array (since C strings have a zero byte as terminator), which might break deletion on your platform and is not safe in general.
No, this is fine, the whole array is deleted. delete doesn't look at what the pointer you give it points to. As long as you match new with delete, and new[] with delete[], the right amount of memory will be freed.
(But do consider using std::string instead of char arrays, that'll avoid a lot of bugs like the one you have there writing past the end of your array.)

Is it possible to use malloc for increasing the size of existing array?

Please tell me, is it possible to use malloc for increasing the size of existing array? (without allocating a new array and then doing memcpy) If yes, how?
See realloc. Note that it might change the address of the array, so be sure to assign the return value.
No, an array requires contiguous memory and there is no way to guarantee that the memory after the current allocation is free. As #James McLaughlin pointed out, you can use realloc in place of creating a new array and then doing a memcopy, but it does essentially the same thing.

C++ Deleting part of dynamic array

Say I have a dynamic array like:
int* integers = new int[100];
Is there a way to delete only part of the array such as:
int* integers2 = integers + 50;
delete[] integers2;
I want to not only delete everything 50 and beyond, but if I call another delete[] on the original integers array, then it would only delete the correct amount of memory and not try to delete the originally allocated amount and seg fault.
Why I want to do this: I have a data structure that is structured in levels of arrays, and I want to be able to create this data structure from a full array. So I want to be able to say
int* level1 = integers;
int* level2 = integers + 50;
int* level3 = integers + 100;
But when level 3 is no longer needed, the data structure will automatically delete[] level3. I need to know that this will behave correctly and not just destroy everything in the array. If it will then I need to just create new arrays and copy the contents over, but it would be nice to avoid doing that for performance reasons.
Edit: Everyone seems to be jumping to the conclusion that I just should use a dynamic resizing container (ie vector, deque) in the first place for my data structure. I am using levels of arrays for a good reason (and they aren't equally sized like I make it look like in my example). I was merely looking for a good way to have a constructor to my data structure that takes in an array or vector and not need to copy the original contents over into the new data structure.
No, this will not behave correctly. You can only delete[] pointers that you got from new[], else the results are undefined and bad things might happen.
If you really need the array to get smaller you have to allocate a new one and copy the contents manually.
Typically when memory gets allocated, there is some housekeeping stuff before the pointer.
i.e. houskeeping (pointer) data
You will mess that up.
int* integers2 = integers + 50;
delete[] integers2;
Will not work because new is created on int*, so space of 100 int has been assigned to integers, now integers2 is only a pointer to 50th location of integers, it has no space assigned to it of its own, so using delete will not delete rest of integers2, it'll only give erratic results.
What you can do is copy the first 50 in another array, and delete the previous array completely.
delete will only delete the pointer which has space assigned to it, using delete to another pointer pointing to the space assigned to first pointer will not delete any space assigned to the first pointer.
delete[] integers2 will not delete any space assigned to integers1 or any other pointer.
Dynamic allocators (like new) generally don't like you releasing part of the memory they gave you. If you use the <malloc.h> defined library functions malloc() and free() instead of new and delete, then you can use realloc(), though in most cases that you would care about the size difference it's just going to copy for you anyway.
Dynamically sizing containers generally use an exponential rule for resizing: if you run out of space, they (for example) double the allocation (and copy the old data over), if you remove data until you are using (for example) less than half the allocation they copy into a smaller allocation. This means you never waste more than half the memory, and the cost of copying per element added or removed is effectively constant. Implementing all of this is a pain in the ass, though, so just use std::vector and let it do it for you :).
No you can't do this with a fixed sized array allocated with new[]. If you want to have a dynamic array use one of the STL containers, such as std::vector.

adding element to an array

How can I add an element to an array where the size of the array is unknown and vectors are prohibited?
If the size of the array is unknown how do you know where to put the element and whether it will fit?
Anyway, if it won't fit you have to allocate a new array that is big enough.
If you allocated originally with malloc rather than new[] you can use realloc. You might be surprised to know that malloc / realloc are not "replaced" by new but are used for a different purpose, and in this case it is a useful thing to use. You can then insert objects into the allocated memory using placement new, and vector works this way. (allocator is used to actually allocate the memory but has an interface like malloc and although the implementation is up to the library author, they will almost certainly use malloc).
If you reallocated using realloc, you need to know that:
Any memory will be copied over. Beware though that if they are non-POD objects stored it is not safe to just do byte-by-byte copy
If realloc fails it returns NULL and your previous array is not freed. Be certain to keep a pointer to the old location until you know realloc worked.
If your array is not POD you cannot realloc, so malloc the new memory and use placement-new with a copy-constructor, then call the destructor on each object of the old memory before freeing it.
Placement new is used so you can allocate more memory than you need for now, i.e. more than you have objects for. This prevents you having to go through this process every single time you append.
I have explained how you might implement vector, but this is probably far too complex for you and probably for your tutor too. So just create an array with new[] and copy over the elements although it is horribly inefficient if you have to do this every time you add one.
You use lists for this purpose. An array is not supposed to be extended.
Your question does not make sense. If you can't use vector, means this is an assignment. I assume you have to use native arrays. If you don't know the size, you just cannot add an element to it. If you knew the size, you would have to allocate a bigger array, copy the contents of the old array plus the new element. Which the vector actually does for you :)
Without knowing the current size of the array and the capacity of the array (the distinction there is important), adding elements to the array is dangerous. You will never know when you have passed the bounds of the array (at least not before your program crashes from a buffer overrun error).
If your professor has banned vector for an assignment, chances are he wants to show you how to manage memory. He's looking for you to create an array using new and properly recognize when you need to allocate a new array of a larger size, copy the original elements, and deallocate the original array using delete.
One hint most professors fail to mention: when you allocate an array using new [], you must also deallocate it using delete [].

Way to increase memory allocated on free store

Is it possible to incrementally increase the amount of allocated memory on a free store that a pointer points to? For example, I know that this is possible.
char* p = new char; // allocates one char to free store
char* p = new char[10]; // allocates 10 chars to free store
but what if I wanted to do something like increase the amount of memory that a pointer points to. Something like...
char input;
char*p = 0;
while(cin >> input) // store input chars into an array in the free store
char* p = new char(input);
obviously this will just make p point to the new input allocated, but hopefully you understand that the objective is to add a new char allocation to the address that p points to, and store the latest input there. Is this possible? Or am I just stuck with allocating a set number.
The C solution is to use malloc instead of new -- this makes realloc available. The C++ solution is to use std::vector and other nice containers that take care of these low-level problems and let you work at a much higher, much nicer level of abstraction!-)
You can do this using the function realloc(), though that may only work for memory allocated with malloc() rather than "new"
having said that, you probably don't want to allocate more memory a byte at a time. For efficiency's sake you should allocate in blocks substantially larger than a single byte and keep track of how much you've actually used.
realloc
You appear to be using C++. While you can use realloc, C++ makes it possible to avoid explict memory management, which is safer, easier, and likely more efficient than doing it yourself.
In your example, you want to use std::vector as a container class for chars. std::vector will automatically grow as needed.
In fact, in your case you could use a std::istreambuf_iterator and std:push_back to std::copy the input into a std::vector.