You need:
*Names = (char **)malloc(sizeof(char **) * (*r));
and consequential changes.
You're passing a triple-pointer in order to be able to return a double-pointer. What you're doing is losing the information about where to store the double-pointer.
There is some truth to the struck out comment; there is also a miscue. A 2D array of strings means that you have three levels of pointer in the basic data. And you need a fourth level of pointer to pass into the function.
Also, using gets() is a recipe for disaster. Don't ever (as in never, as in never ever) use the the gets() function. Not even in toy programs. It gets you into bad habits. The first Internet worm propagated through a program that used gets() (Google search 'morris internet worm').
On Unix and other POSIX-based systems, using fflush(stdin) leads to undefined behaviour. On Windows, the behaviour is defined by Microsoft. If you're running on Windows, then you're OK; if not, you're not.
And I thought Three-Star Programming was bad!
This probably isn't the way I'd do it, but it is a pretty direct translation of what you wrote into something that works, along with a main() program that tests it and frees all the allocated memory. It assumes strdup() is available; if not, it is trivial to write it.
Sample output:
Number of Rows: 2
Number of Columns: 3
R0C0: Row 1, Column 1.
R0C1: Ambidextrous Armless Individual.
R0C2: Data for the third column of the first row.
R1C0: Row 2, Column 1.
R1C1: Row 2, Column 2.
R1C2: Given that the number of rows is 2 and the number of columns is 3, this should be the last input!
Rows = 2, cols = 3.
[0,0] = <<Row 1, Column 1.>>
[0,1] = <<Ambidextrous Armless Individual.>>
[0,2] = <<Data for the third column of the first row.>>
[1,0] = <<Row 2, Column 1.>>
[1,1] = <<Row 2, Column 2.>>
[1,2] = <<Given that the number of rows is 2 and the number of columns is 3, this should be the last input!>>
Working 4-star code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void ReadNames(char ****Names, int *rows, int *cols)
{
char name[100];
printf("Number of Rows: ");
scanf("%d", rows);
printf("Number of Columns: ");
scanf("%d", cols);
int c;
while ((c = getchar()) != EOF && c != '\n')
;
*Names = (char ***)malloc(sizeof(char ***)*(*rows));
for (int i = 0; i < (*rows); i++)
(*Names)[i] = (char **)malloc(sizeof(char **)*(*cols));
for (int i = 0; i < (*rows); i++)
{
for (int j = 0; j < (*cols); j++)
{
printf("R%dC%d: ", i, j);
if (fgets(name, sizeof(name), stdin) == 0)
{
fprintf(stderr, "Unexpected EOF\n");
exit(1);
}
name[strlen(name)-1] = '\0'; // Zap newline
(*Names)[i][j] = strdup(name);
}
}
}
int main(void)
{
int rows;
int cols;
char ***data = 0;
ReadNames(&data, &rows, &cols);
printf("Rows = %d, cols = %d.\n", rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("[%d,%d] = <<%s>>\n", i, j, data[i][j]);
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
free(data[i][j]);
free(data[i]);
}
free(data);
return 0;
}
Alternative 3-star code
Using three levels of pointer is bad enough; four is horrid. This code restricts itself to three levels of pointer. I assume C99 compatibility, so variables can be declared when convenient in a function. The changes to work with C89/C90 compilers (which are 14 years retrograde now) are simple enough.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char ***ReadNames(int *r, int *c)
{
int i, j;
char name[100];
printf("Number of Rows: ");
scanf("%d", r);
printf("Number of Columns: ");
scanf("%d", c);
int x;
while ((x = getchar()) != EOF && x != '\n')
;
char ***Names = (char ***)malloc(sizeof(char ***)*(*r));
for (i = 0; i < (*r); i++)
Names[i] = (char **)malloc(sizeof(char **)*(*c));
for (i = 0; i < (*r); i++)
{
for (j = 0; j < (*c); j++)
{
if (fgets(name, sizeof(name), stdin) == 0)
{
fprintf(stderr, "Unexpected EOF\n");
exit(1);
}
name[strlen(name)-1] = '\0';
Names[i][j] = strdup(name);
}
}
return Names;
}
static void PrintNames(char ***Names, int r, int c)
{
int i, j;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
printf("%s ", Names[i][j]);
printf("\n");
}
}
int main(void)
{
int rows;
int cols;
char ***data = ReadNames(&rows, &cols);
PrintNames(data, rows, cols);
printf("Rows = %d, cols = %d.\n", rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
printf("[%d,%d] = <<%s>>\n", i, j, data[i][j]);
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
free(data[i][j]);
free(data[i]);
}
free(data);
return 0;
}
Example output
Number of Rows: 3
Number of Columns: 4
R1C1
R1C2
R1C3
R1C4-EOR
R2C1
R2C2
R2C3
R2C4-EOR
R3C1
R3C2
R3C3
R3C4-EOR
R1C1 R1C2 R1C3 R1C4-EOR
R2C1 R2C2 R2C3 R2C4-EOR
R3C1 R3C2 R3C3 R3C4-EOR
Rows = 3, cols = 4.
[0,0] = <<R1C1>>
[0,1] = <<R1C2>>
[0,2] = <<R1C3>>
[0,3] = <<R1C4-EOR>>
[1,0] = <<R2C1>>
[1,1] = <<R2C2>>
[1,2] = <<R2C3>>
[1,3] = <<R2C4-EOR>>
[2,0] = <<R3C1>>
[2,1] = <<R3C2>>
[2,2] = <<R3C3>>
[2,3] = <<R3C4-EOR>>
Both programs run clean under valgrind.
the program is not responding- run it in a debugger or stick some printfs in to see where it is getting stuck.