C++ pointer array is still accessible after delete[] is called [duplicate] - c++

This question already has answers here:
c++ delete pointer issue, can still access data [closed]
(6 answers)
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 6 years ago.
In the following code, delete[] is called once to free up the memory allocated by new. However, the array elements is still accessible after delete[] is called. I called delete[] twice to confirm that I am getting a double free or corruption error, which I am getting, which means the memory is freed. If the memory is freed, how am I able to access the array elements? Could this be a security issue which might be exploited, if I am reading something like a password into the heap?
int *foo;
foo = new int[100];
for (int i = 0; i < 100; ++i) {
foo[i] = i+1;
}
cout << foo[90] << endl;
delete[] foo;
cout << foo[90] << endl;
gives the following output
91
91
and
int *foo;
foo = new int[100];
for (int i = 0; i < 100; ++i) {
foo[i] = i+1;
}
cout << foo[90] << endl;
delete[] foo;
delete[] foo;
cout << foo[90] << endl;
gives
*** Error in./a.out': double free or corruption (top): 0x000000000168d010 ***`

The memory is free, which means it isn't attributed anymore, but the compiler's not going to take the extra effort to wipe it back to 0 everytime something's deleted.
It's also not going to take the effort to check that the memory is properly allocated before you access it - it'd reduce performance, and it assumes you don't do so. (Although tools like valgrind or debuggers can detect those wrong calls)
So it just changes the range of the memory as 'unassigned' internally, which means another call to new can use that same memory range. Then whatever data in that memory would be overwritten, and foo[90] won't return the same thing anymore.

Related

C++ – What is the point of the delete keyword? [duplicate]

This question already has answers here:
Why use new and delete at all?
(8 answers)
Use of new and delete in C++
(5 answers)
C++ is it necessary to delete dynamically allocated objects at the end of the main scope?
(7 answers)
Closed 3 years ago.
I am currently learning about dynamically allocated memory and have written a short program for practise.
Here is the main function:
int main() {
// Local variables are stored in the stack.
// The heap is a pool of unused memory that can be used when the program dynamically allocates memory.
// The `new` operator allocates memory within the heap and returns the address of that variable:
int *p = new int;
*p = 5;
cout << "A variable has just been allocated in the heap" << endl;
cout << "Its memory address is: " << p << endl;
cout << "Its value is: " << *p << endl;
// For local variables on the stack, memory management is performed automatically.
// But on the heap, it must be done manually.
// Memory must be freed when no longer needed:
delete p; // This frees up the memory pointed to by p.
// The `delete` keyword frees up the memory allocated for the variable, but does not delete the pointer p, because p is stored on the stack.
// p is now a dangling pointer, it points to a non-existent memory location.
// To test that it worked:
cout << "The memory previously pointed to has now been deleted." << endl;
cout << "Its memory address is: " << p << endl;
cout << "Its value is: " << *p << endl;
}
So far it makes sense, except for line delete p. At that point, the memory is supposed to be 'freed up'. I read the following page for information:
Delete in c++ program is not freeing up memory
The answer said:
Calling delete whatever marks that memory as deallocated and free for future use.
However, when I run the program, the two sets of cout statements output the same thing, which to me suggests that the memory has not been freed up, as p still points to the same location, which has the same value.
After some tinkering, I found that I can reallocate p whether or not I ran delete p and I could change the memory address and its value in either case.
So what exactly does delete p do, I don't notice it making any difference to the program?

Deleting part of array not allowed, why? [duplicate]

This question already has answers here:
Can I delete[] a pointer that points into an allocated array, but not to the start of it?
(7 answers)
Why can't I delete pointer alone from an array of objects?
(4 answers)
Closed 5 years ago.
Consider, below program which gives runtime error. Point of this question is to understand memory view and management.
#include<iostream>
using namespace std;
int main(void) {
char* arr = new char[10];
char* ptr = NULL;
for(int i = 0; i < 10; i++) {
arr[i] = 'a';
}
cout << arr;
ptr = &arr[5];
delete ptr;
cout << arr;
return 0;
}
new allocates a block of memory. You can free that memory using delete, but you must pass the same address that was returned by new. That's how it works. You can't pass arbitrary addresses to delete.
Another option is to use malloc() and free(). These are older function but then you can also use realloc() to resize the memory. Then, if you want to delete part of the array, you can resize it to be smaller. BUT... you must still copy any data as needed to correctly form the resized array. That is not automatic.

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.

Pointers pointing to variables(located on the stack) - C++ [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
I guess this is a very basic question, but even after looking around on the internet for a while I can't seem to find a proper answer to this question.
I will refer to this tutorial on stack/heap:http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html
Let's say I write the following code:
void testVoid() {
int testVariable = 5;
}
If I'm not wrong, this function should create a variable located on the stack. As the functions exits, the allocated memory on the stack is deleted - so my variable should also have been deleted by then.
I have learned that pointers in c++ point to the memory location of a variable.
So if the variable pointed to by a pointer is located on the stack, and the stack then is cleared, I would expect not to be able to access original value through the pointer anymore, since the memory location pointed to is is cleared. However, I tested this:
int* pointer;
void testVoid() {
int num = 3;
pointer = &num; // Here I get the memory location of my num-variable
cout << pointer << " : " << *pointer << endl; // I would get the same result if i printed &num
}
int main(int args, char** argv) {
pointer = new int;
testVoid();
cout << pointer << " : " << *pointer << endl; // I can still access the memory of my num-variable
while (true) {}
return 0;
}
After exiting the testVoid()-function, where the variable is created, I can still get the value of the variable using my pointer. So obviously I have misunderstood something regarding how pointers work in c++. Printing &pointer and &num gives me the same memory location, even after testVoid() has finished. What is the reason for this? If the memory pointed to by the pointer were moved to the heap, shouldn't cout<<&num and cout<
And here's the output:
0024F904 : 3
0024F904 : 3
Just because the value goes out of scope does not mean the memory for the value has been overwritten. You just can't rely on it being stable at that point.

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.