1

I am growing a 2D array by it's column and row size in c programming.

#include <stdio.h>
#include <malloc.h>
//#include <conio.h>
//#include <stdlib.h>

void func(int** p, int d, int** sizes)
{
    static int count = 0;
    int* item = NULL;
    int* temp = NULL;
    if (d == 5) return;
    *sizes = (int*) realloc(*sizes, (d + 1) * sizeof(*sizes));
    *sizes[count] = d + 1; // <=== in second recursive call it throws memory allocation errors here in runtime 

    //p = (int**) realloc(p, (count + 1) * sizeof(int*));

    //printf("%d\n", *sizes[count]);

    //item = (int*) realloc(*(p + d) , *sizes[count] * sizeof(int));
    //if (item) *(p + *sizes[count]) = item;

    ++count;
    func(p, d + 1, sizes);
}

int main()
{
    int* sizes = (int*) malloc(sizeof(int)); // different column sizes of rows
    int** p = (int**) malloc(sizeof(int*));
    *p = (int*) malloc(sizeof(int));
    printf("Hello World!\n");
    func(p, 0, &sizes);
    printf("Hello End!\n");
    getchar();
    free(p);
    return 0;
}

But I am stuck in memory allocation errors. enter image description here Would Someone please help? Am I using realloc() in wrong way? please point my mistakes. Actually I was going to solve a problem in leetcode.com where I required a variable column sized 2D array in c programming. Thus I thought this brainstorinming would help me understand the dynamic 2D array first. Then I will move into the real problem.

EDIT:

#include <stdio.h>
#include <malloc.h>
//#include <conio.h>
//#include <stdlib.h>

void __cdecl func(int** p, int d, int** sizes, int* rows)
{
    int* item = NULL;
    if (d == 5) return;
    *sizes = (int*) realloc(*sizes, (d + 1) * sizeof(*sizes));
    (*sizes)[*rows] = d + 1;

    p = (int**) realloc(p, (*rows + 1) * sizeof(int*));

    printf("%d\n", (*sizes)[*rows]);

    item = (int*) malloc((*sizes)[*rows] * sizeof(int));
    item = (int*) realloc(item , (*sizes)[*rows] * sizeof(int));

    if (item) *(p + *rows) = item;
    p[*rows][(*sizes)[*rows] - 1] = 1;
    printf("item[%d][%d]: %d\n", *rows, (*sizes)[*rows] - 1, p[*rows][(*sizes)[*rows] - 1]);
    ++(*rows);
    func(p, d + 1, sizes, rows);
}

int main()
{
    int rows = 0, i = 0, j = 0;
    int* sizes = (int*) malloc(sizeof(int));
    int** p = (int**) malloc(sizeof(int*));

    *p = (int*) malloc(sizeof(int));

    printf("Hello World!\n");
    func(p, 0, &sizes, &rows);
    printf("Hello End!\n");

    for (; i < rows; ++i)
    {
        int j = sizes[i] - 1;
        printf("p[%d][%d]\n", i, j, p[i][j]); // CAN'T ACCESS HERE
    }

    //for (; i < rows; ++i)
    //{
    //  if (*(p + i))
    //  {
    //      free(*(p + i));
    //      *(p + i) = NULL;
    //  }
    //}
    //free(p);
    //free(sizes);

    getchar();
    return 0;
}

I can't access the array when the recursive function exits performing. I have printed the diagonal values of the 2D array only malloced during recursion. But outside it's showing access violation.

enter image description here

2 Answers2

2

The *sizes[count] does not refer to what you expect here. The operator precedence is first size[count], only then the * operator is applied. To obtain what you expect, you'll have to use:

    (*sizes)[count] = d + 1;

and this must be applied in your commented parts as well, if you want to reuse them.

Vlad Rusu
  • 1,414
  • 12
  • 17
-1

If you are all curious what was my final outcome here it is:

#include <stdio.h>
#include <malloc.h>
//#include <conio.h>
//#include <stdlib.h>

struct ARR
{
    int** p;
};

void __cdecl func(struct ARR* arr, int d, int** sizes, int* rows)
{
    int* item = NULL;
    int iCol = 0;
    if (d == 5) return;

    *sizes = (int*) realloc(*sizes, (d + 1) * sizeof(*sizes));

    (*sizes)[*rows] = d + 1;
    printf("%d=>%d\n", *rows, (*sizes)[*rows]);

    arr->p = (int**) realloc(arr->p, (*rows + 1) * sizeof(int*));

    item = (int*) malloc(sizeof(int));
    item = (int*) realloc(item , (*sizes)[*rows] * sizeof(int));
    if (item) *(arr->p + *rows) = item;

    iCol = (*sizes)[*rows] - 1;
    arr->p[*rows][iCol] = 1;
    printf("item[%d][%d]: %d\n", *rows, iCol, arr->p[*rows][iCol]);
    ++(*rows);
    func(arr, d + 1, sizes, rows);
}

int main()
{
    int rows = 0, i = 0, j = 0;
    struct ARR arr;
    int* sizes = (int*) malloc(sizeof(int));
    arr.p = (int**) malloc(sizeof(int*));

    *(arr.p) = (int*) malloc(sizeof(int));

    printf("Hello World!\n");
    func(&arr, 0, &sizes, &rows);
    printf("Hello End!\n");

    for (; i < rows; ++i)
    {
        int j = sizes[i] - 1;
        printf("p[%d][%d]=%d\n", i, j, arr.p[i][j]);
    }

    for (; i < rows; ++i)
    {
        int j = sizes[i] - 1;       
        free(arr.p[i]);
        arr.p[i] = NULL;
    }
    free(arr.p);
    free(sizes);

    getchar();
    return 0;
}

I hope many programmer will get valuable help from this discussion.

  • 2
    Some observations: [you don't need to cast the result of `malloc()`, and most C programmers do not](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). It is better to avoid explicit types with `sizeof` in `malloc()`, and to use an expression instead: `int* sizes = (int*) malloc(sizeof(int))` --> `int* sizes = malloc(sizeof *sizes)`. This is less error-prone, easier to maintain, and usually easier to read. – ad absurdum Mar 27 '20 at 15:34
  • 2
    `item = (int*) malloc(sizeof(int));` - just `item = NULL`. Same with `sizes = NULL` and `arr.p = NULL`. `realloc` needs a pointer that has been allocated __or NULL__. There is no need to pre-allocate pointers for realloc. – KamilCuk Mar 27 '20 at 15:37
  • 1
    Never use `realloc()` directly; always store the result in a temporary variable and check to see that the allocation succeeded. If a call to `realloc()` fails, a direct assignment loses access to the original memory and is a memory leak. But, in the above code, there is no need to `malloc()` first and then to `realloc()` immediately: [`realloc()` acts on a null pointer as if it were `malloc()`](http://port70.net/~nsz/c/c11/n1570.html#7.22.3.5p3). Also, in general, always check any `malloc()` or `realloc()` to be sure that the allocation was successful. – ad absurdum Mar 27 '20 at 15:37