-3

I define in a loop a bunch of denominators for some divisions to be performed in a future loop, the thing that is bothering me is that the future loop is changing the values of some of them without a statement to do so. As you can see in the code the statement in line 63 is the one causing such a problem, I include some print statements after and before that line to check the problem:

#include <stdio.h>

const int numeroComponentes=3;
const int numeroGrupos=4;

void gammaUNIFAC(double composition[], double RQParameters[][2],  double gruposPorComponente[][numeroComponentes], double gammaResults[][numeroComponentes]);

int main()
{
    
    double composition[numeroComponentes]={0.5719,0.4120,0.0161};
    double RQParameters[numeroGrupos][2]={{0.9011,0.848},{0.6744,0.54},{0.5313,0.4},{1.8701,1.724}};
    double gruposPorComponente[numeroGrupos][numeroComponentes]={{0,0,2},{0,0,5},{0,6,0},{1,0,0}};
    double aParameters[numeroGrupos][numeroGrupos]={{0,0,32.08,601.6},{0,0,32.08,601.6},{15.26,15.26,0,290.1},{27.31,27.31,-66.44,0}};
    double Temperatura=318.0;

    double gammaResults[3][numeroComponentes];
    
    gammaUNIFAC(composition, RQParameters, gruposPorComponente, gammaResults);
    for (int i=0; i<numeroGrupos; i++) {
        for (int j=0; j<numeroComponentes; j++) {
            printf("%f\t", gammaResults[i][j]);
        }
        printf("\n");
    }
    
    return 0;
    
}

void gammaUNIFAC(double composition[], double RQParameters[][2],  double gruposPorComponente[][numeroComponentes], double gammaResults[][numeroComponentes]){
    
    double ri[numeroComponentes]={0};
    double qi[numeroComponentes]={0};
    double sumaGrupos[numeroComponentes]={0};
    double Xmi[numeroComponentes][numeroGrupos]={0};
    double suma_XmiTetami[numeroComponentes]={0};
    double li[numeroComponentes]={0};
    double suma_xili=0;
    double suma_xiqi=0;
    double suma_xiri=0;
    double suma_Xm=0;
    double Tetami[numeroComponentes][numeroGrupos]={0};
    
    for (int i=0; i<numeroComponentes; i++) {
        for (int j=0; j<numeroGrupos; j++) {
            ri[i]=ri[i]+RQParameters[j][0]*gruposPorComponente[j][i];
            qi[i]=qi[i]+RQParameters[j][1]*gruposPorComponente[j][i];
            sumaGrupos[i]=sumaGrupos[i]+gruposPorComponente[j][i];
        }
        printf("denominator %f\t", sumaGrupos[i]);
        printf("\n");
        for (int j=0; j<numeroGrupos; j++) {
            printf("numerator before %f\t", gruposPorComponente[i][j]);
            printf("denominator before %f\t", sumaGrupos[i]);
            Xmi[j][i] = gruposPorComponente[j][i]/sumaGrupos[i];
            printf("numerator after %f\t", gruposPorComponente[i][j]);
            printf("denominator after %f\t", sumaGrupos[i]);
            printf("\n");
            suma_XmiTetami[i] = suma_XmiTetami[i] + Xmi[j][i]*RQParameters[j][1];
        }
        printf("denominator %f\t", sumaGrupos[i]);
        printf("\n");
        li[i] = (10.0/2.0)*(ri[i] - qi[i])-(ri[i] - 1.0);
        suma_xili = suma_xili + li[i]*composition[i];
        suma_xiqi = suma_xiqi + qi[i]*composition[i];
        suma_xiri = suma_xiri + ri[i]*composition[i];
        suma_Xm = suma_Xm + sumaGrupos[i]*composition[i];
        for (int j=0; j<numeroGrupos; j++) {
            Tetami[j][i]=Xmi[j][i]*RQParameters[j][1]/suma_XmiTetami[i];
        }
        printf("\n");
    }
    
    for (int i=0; i<numeroGrupos; i++) {
        for (int j=0; j<numeroComponentes; j++) {
            if (i==0) gammaResults[i][j]=ri[j];
            if (i==1) gammaResults[i][j]=qi[j];
            if (i==2) gammaResults[i][j]=sumaGrupos[j];
        }
    }
    
}

The results that the program throws after execution are:

denominator 1.000000    
numerator before 0.000000   denominator before 1.000000 numerator after 0.000000    denominator after 1.000000  
numerator before 0.000000   denominator before 1.000000 numerator after 0.000000    denominator after 1.000000  
numerator before 2.000000   denominator before 1.000000 numerator after 2.000000    denominator after 1.000000  
numerator before 0.000000   denominator before 1.000000 numerator after 0.000000    denominator after 1.000000  
denominator 1.000000    

denominator 6.000000    
numerator before 0.000000   denominator before 6.000000 numerator after 0.000000    denominator after 6.000000  
numerator before 0.000000   denominator before 6.000000 numerator after 0.000000    denominator after 6.000000  
numerator before 5.000000   denominator before 6.000000 numerator after 5.000000    denominator after 6.000000  
numerator before 0.000000   denominator before 6.000000 numerator after 0.000000    denominator after 0.000000  
denominator 0.000000    

denominator 7.000000    
numerator before 0.000000   denominator before 7.000000 numerator after 0.000000    denominator after 7.000000  
numerator before 6.000000   denominator before 7.000000 numerator after 6.000000    denominator after 7.000000  
numerator before 0.000000   denominator before 7.000000 numerator after 0.000000    denominator after 7.000000  
numerator before 1.000000   denominator before 7.000000 numerator after 1.000000    denominator after 0.000000  
denominator 0.000000    

1.870100    3.187800    5.174200    
1.724000    2.400000    4.396000    
1.000000    0.000000    0.000000    
0.000000    0.000000    0.000000

You can check in the results that the first time the second loop is executed the denominator is not changed, however the second and third times the second loop is executed the denominator is changed in the last iteration of the second loop without a statement to do so in line 63.

Any help would be appreciated because later in the same function I am going to need these values to perform another tasks.

Thanks for your time in advance!

yMor
  • 5
  • 2
  • 1
    `Xmi[j][i]` will become out-of-range unless `numeroComponentes == numeroGrupos` – MikeCAT Mar 27 '21 at 18:39
  • 1
    There are 4 compiler warnings about using uninitialised variables. Namely `suma_xili`, `suma_xiqi`, `suma_xiri`, `suma_Xm`. For example `suma_xili = suma_xili + li[i]*composition[i];`. In C local variables need to be explicitly initialised. – Weather Vane Mar 27 '21 at 18:39
  • @WeatherVane, I fixed the warnings `double suma_xili=0;double suma_xiqi=0; double suma_xiri=0; double suma_Xm=0;` in the declaration statement. – yMor Mar 27 '21 at 18:51
  • @MikeCAT I fixed the problem changing `Xmi[j][i]` to `Xmi[i][j]`, indeed there was a problem in line 63 related to the bounding of `Xmi` Thanks. – yMor Mar 27 '21 at 19:10
  • @yMor `Tetami` has the same problem. – MikeCAT Mar 27 '21 at 19:15
  • @MikeCAT Indeed – yMor Mar 27 '21 at 19:18

2 Answers2

0

numeroGrupos is initialized to 4 but your gammaResults array is of size 3, so you're overwriting memory, which is UB (in your case it's modifying your variable).

Change gammaResults[3][numeroComponentes] to gammaResults[numeroGrupos][numeroComponentes].

Matthieu
  • 2,736
  • 4
  • 57
  • 87
  • @Mathieu I have followed your advice but it did not solve the problem, besides I would need `gammaResults` to have more than `numeroGrupos` in rows in the future for that function – yMor Mar 27 '21 at 18:57
0

@MikeCAT suggested that Xmi[j][i] will become out-of-range unless numeroComponentes == numeroGrupos, in fact making numeroComponentes == numeroGrupos would not solve the problem but the out-of-range suggestion pointed in the right direction to solve it. I have declared numeroGrupos to be 4 and numeroComponentes to be 3 and the statement in line 63 instructed the program to modify the elements Xmi[j][i] in the loop:

    for (int i=0; i<numeroComponentes; i++) {
        for (int j=0; j<numeroGrupos; j++) {
            ri[i]=ri[i]+RQParameters[j][0]*gruposPorComponente[j][i];
            qi[i]=qi[i]+RQParameters[j][1]*gruposPorComponente[j][i];
            sumaGrupos[i]=sumaGrupos[i]+gruposPorComponente[j][i];
        }
        printf("denominator %f\t", sumaGrupos[i]);
        printf("\n");
        for (int j=0; j<numeroGrupos; j++) {
            printf("numerator before %f\t", gruposPorComponente[i][j]);
            printf("denominator before %f\t", sumaGrupos[i]);
            Xmi[j][i] = gruposPorComponente[j][i]/sumaGrupos[i];
            printf("numerator after %f\t", gruposPorComponente[i][j]);
            printf("denominator after %f\t", sumaGrupos[i]);
            printf("\n");
            suma_XmiTetami[i] = suma_XmiTetami[i] + Xmi[j][i]*RQParameters[j][1];
        }
    }

Indeed there was a problem when the second loop was trying to modify the elements of Xmi because Xm[i][j] will become out of range, the statement instructed in some of the iterations that Xm[i][j] were stored in a memory address already taken by sumaGrupos that was storing the denominators for the divisions.

The problem was fixed just changing the declaration of Xmiin line 43 double Xmi[numeroComponentes][numeroGrupos]={0}; that had the dimensions inverted to double Xmi[numeroGrupos][numeroComponentes]={0};. Changing Xm[i][j] to Xm[j][i] also solve the problem as I have suggested in a comment to my question but it was not the real solution though it would avoid accessing the addresses already taken by sumaGrupos.

It was quite educational for me to have committed such an error because I discover the dangers of accessing addresses out-of-range in arrays programming in c as suggested by this post How dangerous is it to access an array out of bounds?, you can even damage your machine or put people in danger without been aware of it.

yMor
  • 5
  • 2