How can I delete dynamic array pointer correctly [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ delete - It deletes my objects but I can still access the data?
Why doesn't delete destroy anything?
I've Created dynamic array, and I added values ​​to the values ​​of the array like that.
int *pArr;
pArr = new int[10];
for(int i=0;i<10;i++){
pArr[i] = i+2;
}
delete[] pArr;
// After deletion I can find the value of the array items.
cout << pArr[5] << endl;
As you see in the code above and in the last line, I can output the fifth element in the array without any problem .
With that supposed to be the array has been removed.

To show that the memory can be used again, consider this expansion of your code:
int *pArr;
pArr = new int[10];
for(int i=0;i<10;i++){
pArr[i] = i+2;
}
delete[] pArr;
int *pArr2;
pArr2 = new int[10];
for(int i=0;i<10;i++){
pArr2[i] = (2*i)+2;
}
cout << pArr[5] << endl;
That prints out 12 for me. i.e. the value from pArr2[5] actually. Or at least I should say it does for my machine with my specific compiler & version, etc. As others have pointed out it is undefined behaviour. But hopefully my example shows you at least one kind of undefined behaviour.

Once you delete[] the array and still try to access the elements of the array it is Undefined Behavior and any behavior is possible.

Yes, this may work, but is not guaranteed to work. Delete [] only invalidates the memory but does not zero it. The memory you are referencing is invalidate at this point. So don't do it :)

You did delete it correctly.
Then, you invoked Undefined Behaviour and found the memory still existed(*) and wasn't zeroed - a tool like valgrind would still show it as a bug though, which it is.
(*) By "still existed" I mean "is accessible to the process" - it could contain anything, but happens not to have been overwritten ... yet.

Related

Why does my dynamic array work without being resized? [duplicate]

This question already has answers here:
No out of bounds error
(7 answers)
Closed 1 year ago.
I'm working on dynamic arrays for my c++ course, but I'm confused about the behavior of my dynamic arrays. For example, if I run this code:
int* myDynamicArr = new int[3];
for (int i = 0; i < 10; i++)
{
myDynamicArr[i] = i + 1;
cout << myDynamicArr[i] << endl;
}
I would expect it to not work since I only declared it as size 3. But when I run it, it prints out 0-9. Same thing if I do this:
char* myCharArr = new char[2];
strcpy(myCharArr, "ThisIsALongString");
cout << myCharArr;
It prints the full string even though it seems like it should fail. Can anyone explain what I'm doing wrong here? Thanks!
C++ does not perform bounds checking on arrays. So when you read or write past the bounds of an array you trigger undefined behavior.
With undefined behavior, your program may crash, it may output strange results, or it may (as in your case) appear to work properly.
Just because it could crash doesn't mean it will.

Deleting an array created by new [] with delete [] [duplicate]

This question already has answers here:
How serious is the new/delete operator mismatch error?
(4 answers)
Closed 6 years ago.
Consider the following piece of code:
#include <iostream>
#include <limits>
using namespace std;
struct my{
int a;
~my(){
cout << "d\n";
}
};
int main(){
my* a = new my[100];
// cout << (void*)a << " " << (void*)&(a[0]) << endl;
delete a; // I know I should use delete [],
// but just to find out what would happen if I do this.
}
The program is printing d and then gives a segmentation fault. The implementation of delete assumes that an area of size sizeof(type) has been allocated and that much memory has to be freed. Whereas delete [] first reads the number of elements which has been allocated. I found that most implementations store this number n in the beginning of the allocated memory. delete [] fetches n from the beginning and the goes on to free n * sizeof(type) bytes of allocated memory. I don't understand why the above program gives segfault. I tried printing the addresses a and &(a[0]) and they are exactly the same, so any possibility that delete was trying to clear the area where n was stored is simply not true. Can someone please tell what is going on?
Note: This does not happen when we allocate arrays of basic types like int, double etc.
The behaviour on using delete on a pointer acquired by new[] is undefined. (Some C++ runtime libraries are implemented in such a way that an array of plain old data types is deleted correctly when you write delete).
Really there is nothing else to say.
what was allocated with new must be freed by delete, what was by new[] must be freed by delete[].
don't mix new for allocating and another APIs to free like Windows GlobalFree().
to delete correctly a:
delete[] a;
if you call delete in a dynamic array will cause an undefined behaviour

Access to infinite array elements? [duplicate]

This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 6 years ago.
I try to understand pointers. Question is: should'nt I get a segmentation fault when compiling the second for loop? If no why not? I could not prevent any access to elements which are outside of y[0][dim].
int main(){
int dim = 3;
int ordnung = 2;
double** y = new double*[ordnung];
for(int i = 0; i<ordnung; i++){
y[i] = new double[dim];
}
for(int i = 0; i<=100; i++){
cout << y[0][i] << endl;
}
delete[] y;
return 0;
}
The output is also confusing me:
0
0
0
1.63042e-332
0
0
0
6.520933e-319
and ongoing zeros. What does that mean?
When you allocate memory using new[], it doesn't initialize the memory in any specific way. Its content is indeterminate and accessing it, even for reading, leads to undefined behavior.
You also go out of bounds of the allocated memory which also leads undefined behavior. C++ have no built-in bounds-checking.
And then you don't free all the memory you allocate. For each new there should be a matching delete, and for every new[] a matching delete[].
Lastly a few notes: First of all if you ever think you need a dynamic array, then your next thought should be std::vector.
And about the memory being uninitialized when using new or new[], that of course depends on what you allocate. If you allocate an object (or an array of objects) with a constructor, that will of course cause the constructor to be called. The constructor may, or may not, initialize the object.

Is this behaviour of delete[] expected - deleting only the first two elements?

My code:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int * p;
p = new int[5];
p[0] = 34;
p[1] = 35;
p[2] = 36;
p[3] = 44;
p[4] = 32;
cout << "Before deletion: " << endl;
for (int i = 0; i < 5; i++)
{
cout << p[i] << endl;
}
delete[] p;
cout << "After deletion: " << endl;
for (int i = 0; i < 5; i++)
{
cout << p[i] << endl;
}
}
If delete[] is supposed to delete all the memory blocks created by the new then why does only the first two elements get deleted here?
This is the output:
Before deletion:
34
35
36
44
32
After deletion:
0
0
36
44
32
One possible reason I could think of is that it removes the first two which some how makes the memory management think that the whole block is free to be reallocated again when needed. Though this is a complete guess on my part and I don't know the real reason.
There's no need to clear (as in change the value) of a deleted element, it only means that the allocator is free to use the space it occupied for whatever it wants, and that accessing the values results in undefined behaviour.
You have experienced a really nasty result of this, which is that some values remain unchanged, while successive runs of the same program might (and you should assume that will) have different results.
It is not the first two items deleted, but all of them. That memory area could now be reused by further new operation, but there is no guarantee what is left in that memory area.
It is completely possible that you would see different results for different machines, subsequent runs on the same machine, different compiler versions and so on. Just do not rely on it.
However, you are accessing a dangling pointer afterwards which is Undefined Behavior (shortly UB).
Just in case, if you call delete without the square brackets, all the memory is de-allocated, but destructors may not be called. That is also UB even though you do not have custom types in this case, just ints.
In your case, it is exactly the same UB behavior with delete as well as delete[], respectively. That is why you see the same results in both cases for your current runs, but then again, even that is not guaranteed.
Ideally, you would need to set them to zero, too, but really, you should consider using a smart pointer, like unique_ptr.
Q: If delete[] is supposed to delete all the memory blocks created by the new then why does only the first two elements get deleted here?
A: The conclusion is incorrect. Try the following:
#include <iostream>
struct A
{
A() : a(0) {}
~A() { std::cout << "Came to ~A(). a = " << a << std::endl;}
int a;
};
int main()
{
A* ap = new A[5];
for (int i = 0; i < 5; ++i )
{
ap[i].a = i;
}
delete [] ap;
}
I get the following output:
Came to ~A(). a = 4
Came to ~A(). a = 3
Came to ~A(). a = 2
Came to ~A(). a = 1
Came to ~A(). a = 0
A pointer is not magic. It is effectively an unsigned integer of machine word size which refers to a memory address. Changing the value of a memory location from whatever it is to 0 is not deleting anything. When you call delete or delete [] all you've done is told the memory allocator that you are done with that memory and it is free to do (or not do) whatever it wants with that memory. After you call delete, what might be in that memory is undefined, you have no right to expect it to contain anything in particular, and you have no right to access it. Accessing memory that has been freed is like entering an apartment that you moved out of that you still have a key to; you might get away with it or you might get an access violation.
For types with destructors, the memory allocator will call the destructor for each object in the block of memory before reclaiming the memory block. ints have no destructor, so there's nothing extra for it to do.
delete[] p releases the memory held by p, but doesn't (necessarily) overwrite it. The old data will remain there indefinitely.

Memory management in C++.

I have the following program:
//simple array memory test.
#include <iostream>
using namespace std;
void someFunc(float*, int, int);
int main() {
int convert = 2;
float *arr = new float[17];
for(int i = 0; i < 17; i++) {
arr[i] = 1.0;
}
someFunc(arr, 17, convert);
for(int i = 0; i < 17; i++) {
cout << arr[i] << endl;
}
return 0;
}
void someFunc(float *arr, int num, int flag) {
if(flag) {
delete []arr;
}
}
When I put the following into gdb and insert a break point at float *arr ..., I step through the program and observe the following:
Printing the array arr after it has been initialized gives me 1 17 times.
Inside someFunc too, I print arr before delete to get the same print as above.
Upon going back into main, when I print arr, I get the first digit as 0 followed by 16 1.0s.
My questions:
1. Once the array has been deleted in someFunc, how am I still able to access arr without a segfault in someFunc or main?
2. The code snippet above is a test version of another piece of code that runs in a bigger program. I observe the same behaviour in both places (first digit is 0 but all others are the same. If this is some unexplained memory error, how am I observing the same thing in different areas?
3. Some explanations to fill the gaps in my understanding are most welcome.
A segfault occurs when you access a memory address that isn't mapped into the process. Calling delete [] releases memory back to the memory allocator, but usually not to the OS.
The contents of the memory after calling delete [] are an implementation detail that varies across compilers, libraries, OSes and especially debug-vs-release builds. Debug memory allocators, for instance, will often fill the memory with some tell-tale signature like 0xdeadbeef.
Dereferencing a pointer after it has been deleteed is undefined behavior, which means that anything can happen.
Once the array has been deleted, any access to it is undefined behavior.
There's no guarantee that you'll get a segment violation; in fact,
typically you won't. But there's no guarantee of what you will get; in
larger programs, modifying the contents of the array could easily result
in memory corruption elsewhere.
delete gives the memory back to the OS memory manager, but does not necessarily clears the contents in the memory(it should not, as it causes overhead for nothing). So the values are retained in the memory. And in your case, you are accessing the same memory -- so it will print what is in the memory -- it is not necessarily an undefined behaviour(depends on memory manager)
Re 1: You can't. If you want to access arr later, don't delete it.
C++ doesn't check for array boundaries. Only if you access a memory which you are not allowed to you will get segfault