The problem is that you loop until *test is a null pointer, but the test array has no null pointers, hence you access the array out of bounds, resulting in undefined behaviour. Allocating space for 4 pointers happens to work probably because the fourth pointer is incidentally a null pointer, but more accurately:
Code:
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
int main()
{
const char **test;
const char *str1 = "string 1";
const char *str2 = "string 2";
const char *str3 = "string 3";
int i = 0;
test = malloc(4 * sizeof(char *));
if (test) {
test[0] = str1;
test[1] = str2;
test[2] = str3;
test[3] = NULL;
while (*test++) {
printf("%d\n", i);
++i;
}
free(test);
} else {
printf("Unable to allocate memory.\n");
}
return 0;
}
Notice that I assign NULL to test[3], hence the loop surely works. I also include <stdio.h> and <stddef.h> for printf and NULL respectively. I deal with const char* instead of char* since the program deals with string literals, and string literals must not be modified. I also used free() when test is no longer to be used, and checked the return value of malloc().