1

I have the following problem: I am populating a 2D array whose number of rows is the number of files I am reading. Therefore the number of columns in each row corresponds to the bytes of data read from the file.

With this picture in mind I have the following program: I have to return a byte array of data read from each file and the size of each file. This is what I have:

void fillArrays(unsigned char **array, size_t dataSize[], int *nFiles)
{
    printf("Calling fillArrays\n"); 
    int i, j, nrows;
    nrows = 3;
    *nFiles = nrows; // assuming no. of files to be read = 3

    dataSize = (size_t *)malloc(nrows * sizeof(size_t));
    array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));

    dataSize[0] = 4; // assuming file 1 contains 4 bytes
    dataSize[1] = 3; // assuming file 2 contains 3 bytes
    dataSize[2] = 1;// assuming file 3 contains 1 bytes

    //populating file data into a 2D array. Here for test purpose assuming each file has data = 0x03!!
    for(i = 0; i < nrows; i++)
    {
        array[i] = (unsigned char *) malloc(dataSize[i] * sizeof(unsigned char));
        for(j = 0; j < dataSize[i]; j++){   
            printf("round %d %d\n", i,j);
            array[i][j] = 0x03;
            printf("array [%d][%d]  = %02X\n ", i, j , array[i][j]); 
        }
        //array[i][dataSize[i]]= '\0';

    }

}


int main(int argc, char *argv[])
{
    unsigned char **fileArray;
    int noFiles = 0;
    size_t *fileSize;

    fillArrays(fileArray,fileSize, &noFiles);
    printf("Returned no. of files = %d\n", noFiles);
    printf("fileSize[0] = %lu\n", fileSize[0]);
    printf("fileSize[1] = %lu\n", fileSize[1]);
    printf("fileSize[2] = %lu\n", fileSize[2]);
    int j = 0;
    for (int i = 0; i <  noFiles; i++){
        printf("i = %d\n", i);
        for (int j = 0; j <  fileSize[i]; j++){
            printf("Obtained data from file %d :  (fileArray [%d][%d])  = %02X\n ", i, i, j , fileArray[i][j]); 
            //j++;
        }
    }


    return 0;
}

the code is segfaulting in the 'j' loop in the main function. Could someone throw some light? How can this be done better?

Thanks.

2 Answers 2

1

You are passing fileArray by value, so in fillArrays you are modyfing copy of this pointer to pointer, so after executing fillArrays function, fileArray in main function is not affected - it is still uninitialized, you need to pass this variable by reference (pass pointer to fileArray):

fillArrays(&fileArray,fileSize, &noFiles);

then in fillArrays you need to add these modifications:

void fillArrays(unsigned char ***array, size_t dataSize[], int *nFiles)
{
    //...
    *array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));
    //...
        (*array)[i] = (unsigned char *) malloc(dataSize[i] * sizeof(unsigned char));
    ///...
            (*array)[i][j] = 0x03;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. In case I keep the function prototype as such, how can I "copy" the array when the function returns from fillarray to main?
@tweetlilly I guess you don't want to use *** ? so declare your function as unsigned char** fillArrays(size_t dataSize[], int *nFiles), define unsigned char** array as local variable instead as parameter and add return array; as last instruction in your function. Call fileArray = fillArrays(fileSize,&noFiles).
1

your array and dataSize are local to fillArrays function and allocating memory to them inside fillArrays will not affect the arrays inside main.

// Allocates the memory to local variables
dataSize = (size_t *)malloc(nrows * sizeof(size_t));
array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));

Hence you need to use pointer to pointer to char* for fileArray and pointer to size_t* for fileSize.

Your prototype will become as below.

void fillArrays(unsigned char ***array, size_t **dataSize, int *nFiles)

And you call the function as below.

fillArrays(&fileArray,&fileSize, &noFiles);

Sample code:

void fillArrays(unsigned char ***array, size_t **dataSize, int *nFiles)
{
    printf("Calling fillArrays\n");
    int i, j, nrows;
    nrows = 3;
    *nFiles = nrows; // assuming no. of files to be read = 3

    *dataSize = (size_t *)malloc(nrows * sizeof(size_t));
    *array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));

    (*dataSize)[0] = 4; // assuming file 1 contains 4 bytes
    (*dataSize)[1] = 3; // assuming file 2 contains 3 bytes
    (*dataSize)[2] = 1;// assuming file 3 contains 1 bytes

    //populating file data into a 2D array. Here for test purpose assuming each file has data = 0x03!!
    for(i = 0; i < nrows; i++)
    {
        (*array)[i] = (unsigned char *) malloc((*dataSize)[i] * sizeof(unsigned char));
        for(j = 0; j < (*dataSize)[i]; j++){
            printf("round %d %d\n", i,j);
            (*array)[i][j] = 0x03;
            printf("array [%d][%d]  = %02X\n ", i, j , (*array)[i][j]);
        }
        //array[i][dataSize[i]]= '\0';

    }

}


int main(int argc, char *argv[])
{
    unsigned char **fileArray;
    int noFiles = 0;
    size_t *fileSize;

    fillArrays(&fileArray,&fileSize, &noFiles);

    printf("Returned no. of files = %d\n", noFiles);
    printf("fileSize[0] = %lu\n", fileSize[0]);
    printf("fileSize[1] = %lu\n", fileSize[1]);
    printf("fileSize[2] = %lu\n", fileSize[2]);
    int j = 0;
    for (int i = 0; i <  noFiles; i++){
        printf("i = %d\n", i);
        for (int j = 0; j <  fileSize[i]; j++){
            printf("Obtained data from file %d :  (fileArray [%d][%d])  = %02X\n ", i, i, j , fileArray[i][j]);
            //j++;
        }
    }


    return 0;
}

Alternate approach:

I suggest you to not have pointer to pointer to char* as parameter instead you just return the filled array from fillArrays as below.

char** fillArrays(size_t **dataSize, int *nFiles)
{
    printf("Calling fillArrays\n");
    int i, j, nrows;
    char **array = NULL;
    nrows = 3;
    *nFiles = nrows; // assuming no. of files to be read = 3

    *dataSize = (size_t *)malloc(nrows * sizeof(size_t));
    array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));

    (*dataSize)[0] = 4; // assuming file 1 contains 4 bytes
    (*dataSize)[1] = 3; // assuming file 2 contains 3 bytes
    (*dataSize)[2] = 1;// assuming file 3 contains 1 bytes

    //populating file data into a 2D array. Here for test purpose assuming each file has data = 0x03!!
    for(i = 0; i < nrows; i++)
    {
        array[i] = (unsigned char *) malloc((*dataSize)[i] * sizeof(unsigned char));
        for(j = 0; j < (*dataSize)[i]; j++){
            printf("round %d %d\n", i,j);
            array[i][j] = 0x03;
            printf("array [%d][%d]  = %02X\n ", i, j , array[i][j]);
        }
        //array[i][dataSize[i]]= '\0';

    }
  return array;
}

and you call the function as below.

fileArray = fillArrays(&fileSize, &noFiles);

1 Comment

Thanks a lot. However with so much pointers I am getting confused. Is there a better way to obtain this 2D array whose size gets known only by a call to fillArray?

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.