You code has several problems, the majority of which could be easily identified by turning your compiler warnings up.
The first problem is that init_data expects a double** as it's first argument, however you're passing a double*** (check your compiler warnings). Since init_data is initialising memory that it's allocating itself, as opposed to initialising a block of memory that you allocated elsewhere, you could remove that first argument and return a double** instead.
You're also allocating an insufficient amount of memory for data. What you want is enough memory for dim_x amount of double*, not double. You can achieve that also with sizeof(*data) (type of *data is double*) instead of sizeof(double*).
data = malloc(sizeof(*data) * dim_x);
Since there are dim_x double*s in data and dim_y doubles in the block of memory pointed to by each of these double*s, your first loop should be iterating up to dim_x, and your second up to dim_y.
Also, casting the result of malloc (casting a void*) in C is unnecessary. There are answers on this site that will tell you why it's preferred that you don't.
Another problem has to do with the printf format specifier. %d is for int, %f is used for double (%lf when using scanf).
Now if you add code to free your allocated memory and run your program through something like valgrind, you'll see that you're no longer doing anything naughty in memory.
The working code would look like:
#include <stdio.h>
#include <stdlib.h>
double** init_data(int dim_x, int dim_y) {
int i,j,k;
double **data = malloc(sizeof(*data) * dim_x); /* hoping not NULL */
for (k = 0; k < dim_x; k++) {
data[k] = malloc(sizeof(**data) * dim_y); /* hoping not NULL */
}
for (i = 0; i < dim_y; i++) {
for (j = 0; j < dim_y; j++) {
data[i][j] = ((double)rand()/(double)RAND_MAX);
}
}
return data;
}
int main(void)
{
double **dataA;
int i, j, dim = 10;
dataA = init_data(dim, dim);
for(i=0; i < dim; i++)
for(j=0; j < dim; j++)
printf("%f\n", dataA[i][j]);
for (i = 0; i < dim; i++)
free(dataA[i]);
free(dataA);
return 0;
}