int** a;
This just gives you a single object. A int** object. It doesn't point anywhere at all. There are no ints to assign to. When you start assigning to the ints as though they exist, you get undefined behaviour.
In addition, the memory layout of an int** pointing to a "2d array" of ints is like so: the int** points at the first element in an array of int*s, and the int*s point at the first elements in an array of ints. This memory is not contiguous because it requires indirection to jump around memory, i.e. it's not a single block of memory. You can't just write to it using memset.
If you just want a fixed compile-time sized 2D array of ints, do:
int a[N][M];
where N and M are constant expressions. This is stored contiguously, but I still don't recommend using memset.
Or use a standard container, such as:
std::array<std::array<int, M>, N> a;
If you need it of dynamic size, try:
std::vector<std::vector<int>> a(M, std::vector<int>(N));
Alternatively, you can stick with your int** and make sure you dynamically allocate the int*s and ints:
int** a = new int*[M];
for (i = 0; i < N; i++) {
a[i] = new int[N];
}
But this is ugly!
a = new int*[m]; for(int i =0; i<m ;i++) a[i] = new int[n];