2

I have a rather unexpected issue with one of my functions. Let me explain. I'm writing a calibration algorithm and since I want to do some grid search (non-continuous optimization), I'm creating my own mesh - different combinations of probabilities. The size of the grid and the grid itself are computed recursively (I know...). So in order:

  1. Get variables
  2. Compute corresponding size recursively
  3. Allocate memory for the grid
  4. Pass the empty grid by reference and fill it recursively

The problem I have is after step 4 once I try to retrieve this grid. During step 4, I 'print' on the console the results to check them and everything is fine. I computed several grids with several variables and they all match the results I'm expecting. However, as soon as the grid is taken out of the recursive function, the last column is filled with 0 (all the values from before are replace in this column only). I tried allocating one extra column for the grid in step 3 but this only made the problem worse (-3e303 etc. values). Also I have the error no matter what size I compute it with (very small to very large), so I assume it isn't a memory error (or at least a 'lack of memory' error). Finally the two functions used and their call have been listed below, this has been quickly programmed, so some variables might seem kind of useless - I know. However I'm always open to your comments (plus I'm no expert in C++ - hence this thread).

void size_Grid_Computation(int nVars, int endPoint, int consideredVariable, int * indexes, int &sum, int nChoices)
{
/** Remember to initialize r at 1 !! - we exclude var_0 and var_(m-1) (first and last variables) in this algorithm **/
 int endPoint2 = 0;

 if (consideredVariable < nVars - 2)
 {
    for (indexes[consideredVariable] = 0; indexes[consideredVariable] < endPoint; indexes[consideredVariable] ++)
    {
        endPoint2 = endPoint - indexes[consideredVariable];
        size_Grid_Computation(nVars, endPoint2, consideredVariable + 1, indexes, sum, nChoices);
    }

 }
 else
 {
    for (int i = 0; i < nVars - 2; i++)
    {
        sum -= indexes[i];
    }
    sum += nChoices;
    return;

 }
}

The above function is for the grid size. Below for the grid itself -

void grid_Creation(double* choicesVector, double** varVector, int consideredVariable, int * indexes, int endPoint, int nVars, int &r)
{
 if (consideredVariable > nVars-1)
    return;
 for (indexes[consideredVariable] = 0; indexes[consideredVariable] < endPoint; indexes[consideredVariable]++)
 {

    if (consideredVariable == nVars - 1)
    {   
        double sum = 0.0;
        for (int j = 0; j <= consideredVariable; j++)
        {
            varVector[r][j] = choicesVector[indexes[j]];
            sum += varVector[r][j];
            printf("%lf\t", varVector[r][j]);
        }
        varVector[r][nVars - 1] = 1 - sum;
        printf("%lf row %d\n", varVector[r][nVars - 1],r+1);
        r += 1;

    }
    grid_Creation(choicesVector, varVector, consideredVariable + 1, indexes, endPoint - indexes[consideredVariable], nVars, r);
 }

}

Finally the call

#include <stdio.h>
#include <stdlib.h>

int main()
{
 int nVars = 5;
 int gridPrecision = 3;


int sum1 = 0;
int r = 0;

int size = 0;
int * index, * indexes;

index = (int *) calloc(nVars - 1, sizeof(int));
indexes = (int *) calloc(nVars, sizeof(int));

for (index[0] = 0; index[0] < gridPrecision + 1; index[0] ++)
{
    size_Grid_Computation(nVars, gridPrecision + 1 - index[0], 1, index, size, gridPrecision + 1);
}

double * Y;

Y = (double *) calloc(gridPrecision + 1, sizeof(double));

for (int i = 0; i <= gridPrecision; i++)
{
    Y[i] = (double) i/ (double) gridPrecision;
}

double ** varVector;

varVector = (double **) calloc(size, sizeof(double *));

for (int i = 0; i < size; i++)
{
    varVector[i] = (double *) calloc(nVars, sizeof(double *));
}



grid_Creation(Y, varVector, 0, indexes, gridPrecision + 1, nVars - 1, r);
for (int i = 0; i < size; i++)
{
    printf("%lf\n", varVector[i][nVars - 1]);
}
}

I left my barbarian 'printf', they help narrow down the problem. Most likely, I have forgotten or butchered one memory allocation. But I can't see which one. Anyway, thanks for the help!

19
  • 3
    Why, oh why is this tagged C++? This is not C++. If you want an answer in C++, they are all going to be variations on "use std::vector ". Also, sscce.org Commented Jan 22, 2013 at 20:49
  • Changed it to the appropriate tag now. As for sscce.org, thanks for the advice but nope, can't make it shorter. The code isn't really what's important but more the issue. However since everytime you post somewhere people ask for code - here you go. Commented Jan 22, 2013 at 20:55
  • The code isn't important? Array's don't randomly initialize themselves to 0. Are we supposed to just be able to look at this code that we've never seen before and immediately know exactly what the problem is? People "ask for code" because without it we cannot help. Since you don't want to try to limit your code yourself, and haven't provided us the means to do so, then I guess you don't really want any help. Commented Jan 22, 2013 at 20:58
  • Also, please don't cast the return value of memory allocator functions. It's unsafe. Commented Jan 22, 2013 at 21:01
  • I should have figured that asking for help would have led to anger. The code is already limited, if you want to discuss the math with me, you'll figure that I can't do much more without losing the main functionality of it. The first function could be taken out but since it is used for the memory allocation, I didn't want to take it out and just put a random value. Commented Jan 22, 2013 at 21:05

1 Answer 1

1

It seems to me that you have a principal mis-design, namely your 2D array. What you are programming here is not a 2D array but an emulation of it. It only makes sense if you want to have a sort of sparse data structure where you may leave out parts. In your case it looks as if it is just a plain old matrix that you need.

Nowadays it is neither appropriate in C nor in C++ to program like this.

In C, since that seems what you are after, inside functions you declare matrices even with dynamic bounds as

double A[n][m];

If you fear that this could smash your "stack", you may allocate it dynamically

double (*B)[m] = malloc(sizeof(double[n][m]));

You pass such beasts to functions by putting the bounds first in the parameter list

void toto(size_t n, size_t m, double X[n][m]) {
 ...
}

Once you have clean and readable code, you will find your bug much easier.

Sign up to request clarification or add additional context in comments.

1 Comment

But this means passing the whole matrix by value doesn't it?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.