I wrote a demo on dynamic 2D arrays:
# include <stdio.h>
# include <stdlib.h>
# define getarray2d(obj, dst) int (* dst)[obj->w] = (int (*)[obj->w])&(obj->data)
typedef struct _myarray {
    int *data;
    size_t h;
    size_t w;
} myarray;
myarray * mallocarray2d(size_t h, size_t w) {
    myarray *arr = (myarray *)malloc(sizeof(myarray));
    int *data = (int *)malloc(h * w * sizeof(int));
    arr->data = data;
    arr->h = h; arr->w = w;
}
void freearray2d(myarray *arr) {
    free(arr->data); free(arr);
}
void printarray2d(myarray *arr) {
    getarray2d(arr, array2d);
    size_t h = arr->h; size_t w = arr->w; size_t i, j;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            printf("%12d  ", array2d[i][j]);
        }
        printf("\n");
    }
}
int main() {
    myarray *arr = mallocarray2d(3, 4);
    printarray2d(arr);
    freearray2d(arr);
}
As expected, output is a "random" array:
F:\Users\23Xor\Desktop>a.exe
  -695987216           555             3             0
           4             0   -1651400550     268491609
  -695968000           555    -695991984           555
But things became interesting after I ran it for multiple times:
F:\Users\23Xor\Desktop>a.exe
   630939408           398     630915408           398
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
 -1688379632           607   -1688403632           607
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
  1305501456           532    1305477456           532
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
   906452752           352     906428752           352
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
 -1575002352           473   -1575026352           473
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
  1594253072           518    1594229072           518
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
   444751632           400     444727632           400
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
Elements at pos (0, 1) (2, 1) (2, 3) are always equal, and elements at pos (0, 2) (0, 3) (1, 0) (1, 1) always remain 3 0 4 0
Is there a specific reason for this?
EDIT: I corrected my faults:
# include <stdio.h>
# include <stdlib.h>
# define getarray2d(obj, dst) int (* dst)[obj->w] = (int (*)[obj->w])(obj->data)
typedef struct _myarray {
    void *data;
    size_t h;
    size_t w;
} myarray;
myarray * mallocarray2d(size_t h, size_t w) {
    myarray *arr = (myarray *)malloc(sizeof(myarray));
    void *data = malloc(h * w * sizeof(int));
    arr->data = data;
    arr->h = h; arr->w = w;
    return arr;
}
myarray * callocarray2d(size_t h, size_t w) {
    myarray *arr = (myarray *)malloc(sizeof(myarray));
    void *data = calloc(h * w, sizeof(int));
    arr->data = data;
    arr->h = h; arr->w = w;
    return arr;
}
void freearray2d(myarray *arr) {
    free(arr->data); free(arr);
}
void printarray2d(myarray *arr) {
    getarray2d(arr, array2d);
    size_t h = arr->h; size_t w = arr->w; size_t i, j;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            printf("%12d  ", array2d[i][j]);
        }
        printf("\n");
    }
}
int main() {
    myarray *arr = mallocarray2d(3, 4);
    printarray2d(arr);
    freearray2d(arr);
}
result:
F:\Users\23Xor\Desktop>a.exe
   630939408           398     630915408           398
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
 -1688379632           607   -1688403632           607
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
  1305501456           532    1305477456           532
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
   906452752           352     906428752           352
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
 -1575002352           473   -1575026352           473
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
  1594253072           518    1594229072           518
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
F:\Users\23Xor\Desktop>a.exe
   444751632           400     444727632           400
  2037603443    1835365491    1666986547    1697539181
  1140876664    1702259058    1952531570     977485153
the last 8 elements even stops changing.
 
    