Deallocating memory using double pointers - c++

Just a question about deallocation through a double pointer.
Would the following basic example be correct?
#include <iostream>
int main()
{
int **d = { new int*[3] };
int * p = { new int[100] } ;
p[0] = 300;
int *x = new int(1);
d[0] = p;
d[1] = x;
// pointer in d[0] is a pointer to an array
// so use this:
delete[] d[0];
// pointer in d[1] is not a pointer to an array
// so use this:
delete d[1];
std::cout << p[0] << " " << x << '\n';
}

You (try to) access p[0] after your delete[] d[0]; call, and d[0] has the p address as its value, so that delete[] call frees the p memory. This means your cout statement is undefined behaviour (when I run it, I get a 'random' value for p[0]).
Move the cout line to before the delete[] d[0] call, and you'll see the value of 300.
Also, you never free the d array! Add this line to near the end of your main: delete[] d;.

Related

Dynamically allocating memory and assigning of individual array values

int main()
{
int *dizi = new int[3];
int *ptr = new int;
*dizi = 1;
*(dizi + 1) = 2;
*(dizi + 2) = 3;
ptr = (dizi + 2);
delete ptr;
for (int i = 0; i < 2; i++)
{
cout << *(dizi + i) << endl;
}
delete[] dizi;
}
I want to return the dizi[2] value but I can't, it just crashes how can I do this, can you give me an example?
Trying to delete ptr is the same as trying to delete dizi[2] as you can read in the comment section delete must be used in an address returned by new. The behavior of your program is undefined.
You also have a memory leak, the memory allocated and assigned to ptr will be inaccessible when you reassign ptr.
If you want to assing the value of dizi + 2 to ptr you would need:
//...
int *ptr = new int;
*ptr = dizi[2]; // or *(dizi + 2);
std::cout << *ptr; // use it
delete ptr; // delete if after use
//...
If, on the ther hand, your intention is to assing dizi + 2 (or &dizi[2]) to ptr, no memory allocation is needed for ptr you can just make the assignment directly:
//...
int *ptr = dizi + 2;
std::cout << *ptr;
//...
Note that, in this case, after the array deletion, ptr becomes dangling, you can no longer use it while it's pointing to dizi + 2.

Why pointer after first iteration points to random values?

Here is my code, and I thought that each cout line will print the respective object the pointer points to. Why is there an error? This prints some random list of numbers, with first always correct.
int* f()
{
int array[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = array;
return p;
}
int main()
{
int* ptr = f();
cout << *(ptr+0) << endl;
cout << *(ptr+1) << endl;
cout << *(ptr+2) << endl;
cout << endl;
}
Your pointer points to array with autamtic storage. The array dies when the function returns and the pointer dangles.
The solution is not using pointer, using vector or dynamic array.
Local arrays are created on the stack, and have automatic storage duration. In your case array is created on the stack and get destroyed when the function f() ends.
there are two ways you can manage so that array remains active through out your program execution.
1) dynamically allocated arrays
//c++
int *array = new int[5];
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
array[4] = 5;
//c++ 11
int *array{ new int[]{ 1, 2, 3, 4, 5 } };
Please always remember to free dynamically allocated array using delete[] if you need to free space.
2) static array
static int array[10] = {1,2,3,4,5,6,7,8,9,10};
Static variables are variables defined using static memory allocation. for more information please see https://en.wikipedia.org/wiki/Static_variable

C++ Pointers and Dynamic Arrays and Delete Operator

Ok so I am going to lay out two programs. Both are dynamic arrays using pointers and the new operator. But one doesn't seem to like the delete operator.
#include <iostream>
int main()
{
int *p;
p = new int[5];
for (int i = 0; i < 5; i++)
{
p[i] = 25 + (i * 10);
std::cout << p[i] << " ";
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
That's the first program. It likes the delete operator just fine. Now the program that dislikes the delete operator:
#include <iostream>
int main()
{
int x;
int *p;
p = new int[5];
*p = 4;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
This program compiles just fine. But during execution, it throws an error - free(): invalid pointer: 0xfdb038 .. or whatever the memory address is for that particular execution. So, the question is:
Why can't the delete operator be used in the second case?
I don't want to have memory leak; I don't want the pointer to be dangling.
If I just say p = NULL;, then p = 0, but I believe the pointer is still dangling?, but I'm not sure. Thanks in advance.
Look at this loop in the second piece of code:
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1; // <--- Here
}
Notice that in this line, you write to the memory address currently pointed at by p. Since you always increment p and then write to it, you end up writing off past the end of the region that you allocated for p. (If we imagine pOrig as a pointer to where p initially points, then this writes to pOrig[1], pOrig[2], pOrig[3], pOrig[4], and pOrig[5], and that last write is past the end of the region). This results in undefined behavior, meaning that literally anything can happen. This is Bad News.
Additionally, delete[] assumes that you are passing in a pointer to the very first element of the array that you allocated. Since you've incremented p so many times in that loop, you're trying to delete[] a pointer that wasn't at the base of the allocated array, hence the issue.
To fix this, don't write to p after incrementing it, and store a pointer to the original array allocated with new[] so that you can free that rather than the modified pointer p.
You have to delete the pointer that you got from new. However, in your second code you did p++ which changed the pointer. Therefore you tried to delete a pointer you didn't get from new and delete crashes.
To fix this type of error never use new. Instead use std::vector<int> p;. Since you never need new you cannot forget a delete.
Problem is changing p in p++.
You should always store (to delete) original pointer. Like this:
#include <iostream>
int main()
{
int *original = new int[5];
int *p = original;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
int x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] original;
return 0;
}

Deleting dynamic array using another pointer

The situation is:
int main ()
{
int *p1 = new int[50];
int *p2 = p1;
...
When I want to delete my array I do:
delete[] p1;
Can I do it also with this:
delete[] p2;
?
Both pointers are pointing to the same memory, so you can use either one when you delete[]. But only do it once, deleting already deleted memory is undefined behavior. So if you do delete[] p1; then you can't do delete[] p2; as well, it's one or the other.
If not to delve into the details the definition of the delete operator looks the following way
delete expression
delete [ ] expression
As you can see it uses an expression (more precisely a cast expression). For example you could write
int *p1 = new int[50];
int *p2 = p1 + 50;
delete [] ( p2 - 50 );
(Notice that you have to enclose in parentheses expression p2 - 50.)
The expression is evaluated and its values is used as the address of the memory being deleted.
After deleting the memory you may not access it. Otherwise the bahaviour of the program will be undefined.
Since p2 points to the same block of memory that was allocated by p1 then yes, p2 can be used to erase that block of memory.
You can verify this by running the following code...
#include <iostream>
using namespace std;
int main()
{
int* p1 = new int[10];
int* p2 = nullptr;
for (int i = 0; i < 10; i++) {
p1[i] = i * i;
}
// 1st run
for (int i = 0; i < 10; i++) {
cout << p1[i] << " ";
}
cout << endl;
p2 = p1;
if (p2 != nullptr) {
delete p2;
}
// 2nd run;
for (int i = 0; i < 10; i++) {
cout << p1[i] << " ";
}
p1 = nullptr;
p2 = nullptr;
return 0;
}
The 2nd run through the p1 array shows that the content of that array was deleted by the delete p2 operation which was put in an if statement for safety.
The two pointers can be put to rest, once their use is over, by equating them to nullptr keyword.

How to set pointer to an int array to NULL in C++?

For a pointer to an int, I can do -
int *p = new int;
*p = 10;
delete p; // Step 1: Memory Freed
p = 0; // Step 2: Pointer set to NULL
Now, if I have a pointer to an int array -
int *p = new int[10];
p[1] = 1;
p[5] = 5;
delete[] p; // Step 1: Memory freed corresponding to whole array
Now, how to achieve 'Step 2' for this case?
You don't have an array of int pointers. You just have an array of int. Since you only have one pointer, p, you can just do the same thing as you did previously:
p = 0; // or nullptr, preferably
If you did have an array of int pointers, you will probably have allocated them in a loop. In the same way, you can deallocate them and set them to 0 in a loop:
int* array[10];
for (auto& p : array) {
p = new int;
}
// Some time later...
for (auto& p : array) {
delete p;
p = 0;
}
Do consider whether you need to set your pointers to null after deleteing them.