If MSVC doesn't support VLAs, but your code expects to index into arr as arr[i][j], then you're going to have get creative.
If your array contents need to be contiguous, then you need to allocate a single backing store:
int *store = malloc( dim * dim * sizeof *store );
and then allocate arr as an array of pointers into that storage:
int **arr = malloc( dim * sizeof *arr );
for ( size_t i = 0; i < dim; i++ )
  arr[i] = store + i * dim;
Which gives us something like this:
     int **      int *                  int
     +---+      +---+                   +---+
arr: |   | ---> |   | arr[0] ---------> |   | arr[0][0]  (store[0])
     +---+      +---+                   +---+
                |   | arr[1] -------+   |   | arr[0][1]  (store[1])
                +---+               |   +---+
                 ...                |    ...
                +---+               |   +---+
                |   | arr[dim-1] -+ |   |   | arr[0][dim-1] (store[dim-1])
                +---+             | |   +---+
                                  | +-> |   | arr[1][0] (store[dim])
                                  |     +---+
                                  |     |   | arr[1][1] (store[dim+1])
                                  |     +---+
                                  |      ...
                                  |     +---+
                                  |     |   | arr[1][dim-1] (store[dim+dim-1])
                                  |     +---+
                                  |      ...
                                  |     +---+
                                  +---> |   | arr[dim-1][0] (store[dim*(dim-1)])
                                        +---+
                                        |   | arr[dim-1][1] (store[dim*(dim-1)+1]
                                        +---+
  
     
If your array doesn't need to be contiguous, you can do a "jagged" allocation:
int **arr = malloc( dim * sizeof *arr ); // allocates your "columns"
if ( arr )
{
  size_t i;
  for ( i = 0; i < dim; i++ )
  {
    arr[i] = malloc( dim * sizeof *arr[i] ); // allocates your "rows"
  }
}
arr is a pointer to a dim-element array of int *, and each arr[i] is a pointer to a dim-element array of int, giving you something like this:
     int **      int *                      int
     +---+       +---+                      +---+
arr: |   | ----> |   | arr[0] ------------> |   | arr[0][0]
     +---+       +---+                      +---+
                 |   | arr[1] ----------+   |   | arr[0][1]
                 +---+                  |   +---+
                  ...                   |    ...
                                        |   
                                        |   +---+
                                        +-> |   | arr[1][0]
                                            +---+
                                            |   | arr[1][1]
                                            +---+
                                             ...
Note that if you're passing arr to any functions, the corresponding function argument must have type int **, not int (*)[dim] or int [][dim] or int [dim][dim].