简体   繁体   中英

Array of Pointers getting garbage value in c++

I'm trying to create an array of pointers to a 2D (5 X 12) array in C++. The ptr array has 5 elements. Each element should hold the address of the 1st element of the respective row of the 2D array. So 1st element should point to 1st element of 1st row, 2nd element should point to 1st element of 2nd row, and so on. The 5th element of my array of pointers seems to point to a garbage value.

Code and output shown below. Can anyone please let me know why?

#include <iostream>
#include <cstdlib>
#include <iomanip>
using namespace std;
int main( )
{
   int rainMatrix[5][12] = {{0}}; //declare and initialize rain matrix
   int *matrix_ptr[5] = {NULL};//declare and initialize array of pointers
   int **matrix_ptr_ptr = matrix_ptr;

   for (int i = 0; i < 5; ++i)
      matrix_ptr[i] = &rainMatrix[i][0];

   rainGen(matrix_ptr_ptr, 5, 12); //generate a random matrix

   //display the matrix
   for (int i = 0; i < 5; ++i) {
      for (int j = 0; j < 12; ++j) {
         cout << setw(2) << rainMatrix[i][j] << " ";
      }
      cout << endl;
   }

   for (int i = 0; i < 5; ++i)
      cout << setw(2) << *matrix_ptr[i] << "  " << rainMatrix[i][0] << endl;

   return 0;
}

void rainGen (int **pptr, int row, int col)
{
   unsigned int seed = 43;
   unsigned int rv;

   srand(seed);

   for (int i = 0; i < row; ++i) {  
        for (int j = 0; j < col; ++j) {
            rv = rand() % 100;
            **pptr = rv;
            *pptr += 1;
        }
        pptr++; 
    }
}

OUTPUT

11  1
88  11
28  88
25  28
1477892712  25

You are modifying the pointers in the pointer-array matrix_ptr within your rainGen function, so that all of them point past the end and further accesses go to "random" memory locations, which is undefined behavior . Tools like valgrind can find such errors.

You're manipulating the wrong pointer in the innermost loop. Consider the pointer arithmetic carefully:

  • pptr essentially points to matrix_ptr[0] ;
  • on the first iteration, the double indirection means **pptr will set what you want, but then
  • *pptr += 1 will modify the contents of matrix_ptr[0] , which means it no longer points to the beginning of the matrix .

Subsequent passes through the loop compound the situation drastically.

Modifying pptr won't help because it actually points to the wrong thing: it points to matrix_ptr , so incrementing it merely once moves its address from that of matrix_ptr[0] , which points to rainMatrix[0][0] , to that of matrix_ptr[1] , which points to rainMatrix[1][0] . That is the wrong address for the next entry of the matrix, which is rainMatrix[0][1] . In essence, you've moved to the next row, instead of to the next column.

Try this for the innermost loop instead:

for (int i = 0; i < row; ++i)
    {   
        auto qptr = *pptr;
        for (int j = 0; j < col; ++j)
        {
            rv = rand() % 100;
            *qptr = rv;
            qptr += 1;
        }
        pptr++;

    }
}

In this case, qptr is given the address of the first entry in the matrix. *qptr = rv sets the value. qptr += 1 increments the position of qptr while leaving *pptr alone - and, by extension, it leaves matrix_ptr[0] alone.

John Perry correctly identified the problem, but you have several option to deal with it. You are incorrectly incrementing *pptr += 1 Beyond using auto , you can simply index the pointer with the offset of j , eg

*(*pptr + j) = rv;

or

(*pptr)[j] = rv;

Either will work. Putting it together in your rainGen function, you could do:

void rainGen (int **pptr, int row, int col)
{
    unsigned int seed = 43;
    unsigned int rv;
    srand(seed);

    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < col; ++j) {
            rv = rand() % 100;
            // *(*pptr + j) = rv;   /* or */
            (*pptr)[j] = rv;
        }
        pptr++;
    }
}

( note: seed and srand(seed) should be moved to main() if there is the potential that rainGen could be called more than once -- srand should only be called once)

Example Use/Output

Both will produce the desired output:

$ ./bin/raingen
72 71 65 94  0 13 49 17 36 49 67 51
87 68 45 15 91 72 16 80 77 35  9 81
11 88 73 59 24 22 37 48 45 54 94 45
19 44 62 56 45 81 59 32 49  4 99 92
28 16 24  5  3 34 38 14 22 12 26 98
72  72
87  87
11  11
19  19
28  28

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM