Is this pointer dangling pointer at the end of the program?

My question is simple,
is the pointer at the end of this array a dangling? (after all the deallocation is performed)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<iostream>
using namespace std;
int main()
{
	int noOfarr=4, rows=5,cols=10;
	int ***arr;
	arr = new int**[noOfarr];

	for (int i = 0; i < noOfarr; i++)
	{
		arr[i] = new int*[rows];
		for (int j = 0; j < rows; j++)
		{
			arr[i][j] = new int[cols];
		}

	}
	cout << "Please Populate 3D Array: ";
	for (int i = 0; i < noOfarr; i++)
	{
		for (int j = 0; j < rows; j++)
		{
			for (int k = 0; k < cols; k++)
			{
				cin >> *(*(*(arr + i) + j) + k);
			}
		}
	}
	for (int i = 0; i < noOfarr; i++)
	{
		for (int j = 0; j < rows; j++)
		{
			for (int k = 0; k < cols; k++)
			{
				cout << *(*(*(arr + i) + j) + k)<<" "; 
			}
			cout << endl;
		}
		cout << endl << endl;
	}
	for (int i = 0; i > rows; i++)
	{
		for (int j = 0; j > cols; j++)
		{
			delete[]	arr[i][j];
		}
		delete[] arr[i];
	}
	delete[] arr;
	system("pause");
	return 0;
}
its easy to test.
when you delete a pointer, set it to null. This is good practice for many reasons.
is your pointer null? it is clean. Not null? You forgot to delete and null it.
It looks like you've cleaned up properly. But, yes, arr is "dangling" after the delete since delete doesn't set it to nullptr after deallocating the memory it points to. So you still have that address in arr, but using it is undefined behavior.

BTW, you can allocate the entire data block contiguously (and, incidentally, the block of row pointers, too).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
    size_t depth{ 2 }, rows{ 3 }, cols{ 4 };

    // Allocate
    auto a{ new int**[depth] };
    
    a[0] = new int*[depth * rows]; // allocate block of row pointers
    for ( size_t d{ 1 }; d < depth; ++d ) // set remaining depth pointers
        a[d] = a[d - 1] + rows;

    a[0][0] = new int[depth * rows * cols] {}; // allocate block of data elements (and default-fill)
    for ( size_t dr{ 1 }; dr < depth * rows; ++dr ) // set remaining row pointers
        a[0][dr] = a[0][dr - 1] + cols;

    // Fill data block with consecutive values.
    int* p{ &a[0][0][0] };
    for ( size_t i{}; i < depth * rows * cols; ++i ) *p++ = i;

    // Print
    for ( size_t d{}; d < depth; ++d )
    {
        for ( size_t r{}; r < rows; ++r )
        {
            for ( size_t c{}; c < cols; ++c )
                cout << setw(3) << a[d][r][c] << ' ';
            cout << '\n';
        }
        cout << '\n';
    }

    // Delete
    delete[] a[0][0];
    delete[] a[0];
    delete[] a;
}

Output
  0   1   2   3 
  4   5   6   7 
  8   9  10  11 

 12  13  14  15 
 16  17  18  19 
 20  21  22  23 

It would be best to make this a class so it's size information was encapsulated.
Last edited on
Topic archived. No new replies allowed.