For loop error with 2D dynamically allocated array

I'm having an issue with writing values to my 2D array that I've dynamically allocated. It seems that it is writing values to other spots in the array when it should not be.

As far as I can tell I've allocated the memory correctly and I don't believe my iterations are off.

When I try defining an array as double KAB[3][15]={0.0} I do not have this problem.

In this example, obviously, I'm using specific lengths of the array, but I would like them to work when defined by the user. Any trouble shooting suggestions would be appreciated.

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string.h>



int main( ) 
{

int ms=0,i=0,j=0,n=0;
double value=0;
    double **KAB;
    KAB = (double **) malloc(3 * sizeof(double **));//makes array of pointers
    for(i = 0; i < 15; i++)
    {
        KAB[i] =(double *) malloc(3 *sizeof(double*));//each pointer points to a certain number of doubles
    }

        for(i=0;i< 3;i++)
        {
            for(j=0;j< 15;j++)
            {
                KAB[i][j]=0.0;//each value is set to 0.
            }
        }

for(ms=0; ms < 3; ms++)
{   
    for(i=0; i<15;i++)
    {       
        value=0;
        for(n=0; n<5 ;n++)
        {
                value+=ms*1.0+1;    
        }
        KAB[ms][i]=value;

        printf("Step:%d MS:%d\n",i,ms);
        printf("KAB[0][7]=%lf KAB[1][7]=%lf KAB[2][7]=%lf\n",KAB[0][7],KAB[1][7],KAB[2][7]);
    }
    }

return 0;
}//ends main    

I've included relevant output with some annotations.

MS:0 Step:0
KAB[0][7]=0.000000, KAB[1][7]=0.000000, KAB[2][7]=0.000000
MS:0 Step:1

Everything starts at 0. And the first value gets put in the right spot.

MS:0 Step:7
KAB[0][7]=5.000000, KAB[1][7]=0.000000, KAB[2][7]=0.000000

But Before the end of the ms=0 loop something is written to the second row of the array

MS:0 Step:11
KAB[0][7]=5.000000, KAB[1][7]=5.000000, KAB[2][7]=0.000000

During the third step of the ms=1 loop the first row gets over written

MS:1 Step:3
KAB[0][7]=10.000000, KAB[1][7]=5.000000, KAB[2][7]=0.000000

At the appropriate step, the second row, column seven value gets the correct value entered

MS:1 Step:7
KAB[0][7]=10.000000, KAB[1][7]=10.000000, KAB[2][7]=0.000000

But before the rest of the row is finished the same value gets put into the next row in the same column.

MS:1 Step:11
KAB[0][7]=10.000000, KAB[1][7]=10.000000, KAB[2][7]=10.000000

the second row gets replaced with some values from the third row

MS:2 Step:3
KAB[0][7]=10.000000, KAB[1][7]=15.000000, KAB[2][7]=10.000000

The third row gets it's correct value. These values remain until the end, but clearly the first and second rows have some incorrect values.

MS:2 Step:7
KAB[0][7]=10.000000, KAB[1][7]=15.000000, KAB[2][7]=15.000000

2 answers

  • answered 2018-09-16 00:46 Anupam

    You are not doing malloc properly.

    KAB = (double **) malloc(3 * sizeof(double **));
    

    This statement is wrong and will allocate an array of double * but you need an array of double * because each element inside KAB should be a double * to point to an array of doubles and not a double **

    Similar is the case with the following statement

    KAB[i] =(double *) malloc(3 *sizeof(double*));
    

    Here, you are allocating an array of double * instead, it should be an arrray of doubles.

    The following code would work correctly.

    #include <stdlib.h>
    #include <stdio.h>
    #include <math.h>
    #include <time.h>
    #include <string.h>
    
    
    
    int main() 
    {
    
        int ms=0,i=0,j=0,n=0;
        double value=0;
        double **KAB;
        KAB = (double **) malloc(3 * sizeof(double *));//makes array of type double pointers
        for(i = 0; i < 15; i++)
        {
          KAB[i] =(double *) malloc(3 *sizeof(double));//each element in KAB points to an array of doubles
        }
    
          for(i=0;i< 3;i++)
          {
            for(j=0;j< 15;j++)
            {
                KAB[i][j]=0.0;//each value is set to 0.
            }
          }
    
        for(ms=0; ms < 3; ms++)
        {   
            for(i=0; i<15;i++)
            {       
              value=0;
              for(n=0; n<5 ;n++)
              {
                      value+=ms*1.0+1;    
              }
              KAB[ms][i]=value;
    
              printf("Step:%d MS:%d\n",i,ms);
              printf("KAB[0][7]=%lf KAB[1][7]=%lf KAB[2][7]=%lf\n",KAB[0][7],KAB[1][7],KAB[2][7]);
            }
        }
        return 0;
    }//ends main 
    

  • answered 2018-09-16 14:52 user3121023

    Besides the issues of double** and double*(both of these allocate four bytes on my system, but the malloc in the loop needs double to allocate eight bytes), the first malloc allocates memory for three pointers, but the next loop tries to iterate over fifteen pointers. This leads to confusion. Do you want to allocate memory arranged as [3][15] or [15][3] or even [3][3].
    Here is an allocation strategy that may help eliminate the confusion.
    Use define to define COLS and ROWS. When compiling, the preprocessor will replace COLS with 15 and ROWS with 3.
    Instead of declaring a pointer to poiiter **KAB, declare a pointer to array (*KAB)[COLS]. With this, one call to calloc will allocate the memory for [ROWS][COLS] and initialize to zero. Similarly, one call to free will release the allocated memory.

    #include <stdlib.h>
    #include <stdio.h>
    
    #define ROWS 3
    #define COLS 15
    
    int main( void)
    {
        int row = 0;
        int col = 0;
        double (*KAB)[COLS] = NULL;
    
        if ( NULL == ( KAB = calloc ( ROWS, sizeof( *KAB))))//allocate ROWS of [COLS]
        {
            fprintf ( stderr, "calloc problem\n");
            return 0;
        }
    
        for ( row = 0; row < ROWS; row++)
        {
            for ( col = 0; col < COLS; col++)
            {
                KAB[row][col] = ( row + 1) * 5;
    
                printf ( "Row:%d Col:%2d   ", row, col);
                printf ( "KAB[0][7]=%6.2f      ", KAB[0][7]);
                printf ( "KAB[1][7]=%6.2f      ", KAB[1][7]);
                printf ( "KAB[2][7]=%6.2f\n",     KAB[2][7]);
            }
        }
    
        free ( KAB);
        KAB = NULL;
    
        return 0;
    }