I am trying to return a modern 2D dynamic array after allocating memory to it and filling it up with character values. I tried working around some errors but ultimately got stuck at a dead end. I originally had a working 2D dynamic array implementation return in functions using array-of-pointers method from C90 but I am told that has overhead and is out-of-date. So, I decided to try and upgrade using modern C 2D array approach taken from here: How do I work with dynamic multi-dimensional arrays in C?.
Alas, it ended up not working in my implementation so I am now wondering what I may have done wrong. Please see my below code for full reference: (Goal was to make a 2D matrix of a checkerboard within helper functions to main)
char **allocateToBoardC99(const int nthDim)
{
    char(*boardArray)[nthDim] = malloc(sizeof(char[nthDim][nthDim]));
    return (char **)boardArray;
}
char **getCheckeredBoardC99(const int nthDim)
{
    bool startWithWhiteTile = true;
    // C99 version (more elegant):
    char **arr = allocateToBoardC99(nthDim);
    // Make the board checkered by alternating char assignments based on a bool latch
    for (int rowIndex = 0; rowIndex < nthDim; rowIndex++)
    {
        if (startWithWhiteTile)
        {
            for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
            {
                arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'W' : 'B';
            }
            startWithWhiteTile = false;
        }
        else
        {
            for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
            {
                arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'B' : 'W';
            }
            startWithWhiteTile = true;
        }
    }
    return (char **)arr;
}
int main(int argc, char *argv[])
{
    // Initialize dimension of the checker board:
    int dim = 8;
    // char **boardMatrix = getCheckeredBoardC90(dim); // Works
    char **boardMatrix = getCheckeredBoardC99(dim);
    printf("hello world");
    printf("\n");
    for (int row = 0; row < dim; row++)
    {
        printf("[");
        for (int column = 0; column < dim; column++)
        {
            printf("%c ", boardMatrix[row][column]);
        }
        printf("]\n");
    }
    return 0;
}
If you're curious about the above getCheckeredBoardC90(dim); working, here is the following sequence of code that made it work (while the newer C99 doesn't):
char **allocateToBoardC90(const int nthDim)
{
    // The calloc() function reserves storage space for an array of NUM elements, each of length SIZE bytes:
    // calloc(size_t NUM, size_t SIZE)
    char *values = calloc(nthDim * nthDim, sizeof(char)); // In our 2D board array, we would have nxn (char)elements (8x8=64 elements)
    // Simple way is to allocate a memory block of size row and access its elements using simple pointer arithmetic:
    char **rows = malloc(nthDim * sizeof(char)); // pointer to overall space
    // Iterate through each *row; 0 to nthRow
    for (int rowIndex = 0; rowIndex < nthDim; rowIndex++)
    {
        rows[rowIndex] = values + (rowIndex * nthDim);
    }
    // Returns an array of pointers (array of arrays)
    return rows;
}
char **getCheckeredBoardC90(const int nthDim)
{
    bool startWithWhiteTile = true;
    //**array[rowIndex][columnIndex]
    // char **arr[nthDim][nthDim];
    // C90 version (lotta pointers; be aware of performance overhead):
    char **arr = allocateToBoardC90(nthDim);
    // Make the board checkered by alternating char assignments based on a bool latch
    for (int rowIndex = 0; rowIndex < nthDim; rowIndex++)
    {
        if (startWithWhiteTile)
        {
            for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
            {
                arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'W' : 'B';
            }
            startWithWhiteTile = false;
        }
        else
        {
            for (int columnIndex = 0; columnIndex < nthDim; columnIndex++)
            {
                arr[rowIndex][columnIndex] = (columnIndex % 2 == 0) ? 'B' : 'W';
            }
            startWithWhiteTile = true;
        }
    }
    return arr;
}
int main(int argc, char *argv[])
{
    // Initialize dimension of the checker board:
    int dim = 8;
    char **boardMatrix = getCheckeredBoardC90(dim); // Works
    // char **boardMatrix = getCheckeredBoardC99(dim);
    printf("hello world");
    printf("\n");
    for (int row = 0; row < dim; row++)
    {
        printf("[");
        for (int column = 0; column < dim; column++)
        {
            printf("%c ", boardMatrix[row][column]);
        }
        printf("]\n");
    }
    return 0;
}
If the helper functions return correctly, then main's output should look something like this:
hello world
[W B W B W B W B ]
[B W B W B W B W ]
[W B W B W B W B ]
[B W B W B W B W ]
[W B W B W B W B ]
[B W B W B W B W ]
[W B W B W B W B ]
[B W B W B W B W ]
Specific help on this would be greatly appreciated, thank you!
NOTE: Originally with this dynamic 2D array modern C code, I was trying to return the 2D array from an allocator function (really a reference to it), pass that 2D array's reference to an element-initializer function to fill up the checkerboard like usual, and then finally pass the finalized 2D array (as a reference) to the main function to check the contents of the 2D array through terminal output.
What ended up happening was a lot of trial and error to resolve pointer-to-object issues, pointer casting, etc. This only led (from what I believe is improper C-pointer casting) to an end-game "Segmentation Fault" in the getCheckeredBoardC99 function.
 
     
    