yesterday I had posted a question: How should I pass a pointer to a function and allocate memory for the passed pointer from inside the called function?
From the ans
In your alloc_2D_pixels function, you need another level of indirection when accessing memory. As it is now, you only modify the parameter, not the pointer pointed to by the parameter. For example,
memory = malloc(rows * sizeof(unsigned char** ));
// becomes
*memory = malloc(rows * sizeof(unsigned char** ));
// and later...
memory[i] = malloc(cols * sizeof(unsigned char));
// becomes
(*memory)[i] = malloc(cols * sizeof(unsigned char));
(basically, anywhere you are using memory, you need to use (*memory); the parentheses are only needed when you are using subscripts to ensure that the operators are applied in the correct order)