Как разобраться с выделением памяти в массиве?
Если правильно понял вопрос, то можно выделить память единым куском под всю матрицу:int* matr = (int*)malloc(n * m * sizeof(int));а к конкретной ячейке обращаться как matr[i * n + j]
тогда и освободить будет просто - free(matr) и все.

а для текущего примера освобождение памяти будет выглядеть так:void free_matr(int m, int** matr) {
  for(int i = 0; i < m; i++) {
    free(matr[i]);
  }
  free(matr);
}
Я так понял - сперли откуда-то кусок кода, но понять, как это работает, тяму не хватает. Да и код-то фиговый.

int** inmatr(int m,int n){
    int *matr;
    int i,j;

    if ((matr=(int*) сalloc(m * n, sizeof(int))) == NULL)
      {
         puts("Memory alloc error");
         exit(100);
      }

    for (i=0; i<m; i++){
        for (j=0;j<n;j++){
            printf("a[%d][%d] = ", i, j);
            scanf("%d", &matr[i][j]);
        }
    }
    return &matr;
}

Проверка успешности выделения памяти делается банально просто - если память не выделена, целевая переменная равна NULL. Выделять память не только можно, но и нужно сразу - размер матрицы же известен сразу. Только разумеется не массив указателей на целое, а массив целых.
Возвращается адрес области, куда записали адрес области под матрицу. Хотя я бы передавал переменную (тип **int) из вызывающей функции.
Освобождается память через free(). Но освобождение невыделенной памяти может запросто привести к SIGSEGV.