there are a few things I'd like to add :
1) in this case : the array of pointer could have been created statically, then the problem would not arise. As long as things are not too big so they fit nicely on the stack, just create them there and not from the heap
2) when sticking to the heap case, always initialize memory you get. So the array of pointers should have been directly initialized to 0 ( yes 0 : not NULL, the 'fake' (key)word NULL is not standard, the number 0 is !!!) that way you would have gotten a crash (on PC) directly because of dereferencing NULL and not some weird outbounded random value which then acts as the memory address. Offcourse when the memset would also have worked with the incorrect length then again you end up at the random values. But then you had to make the mistake twice ( or once if you would have made a variable out of the length).
[memset(s, 0, MAX*sizeof(*s))]
Why 'sizeof(*s)" : if the type of s changes I don't have to adjust this statement <--> sizeof(char) becoming sizeof(int)
Note : I said on PC, because on embedded platforms the address 0 just acts as any regular address, you are just screwing up things somewhere else :-(
RAII : Resource Acquisition Is Initialisation
Extra Note : Alexandrescu has sone nifty methods for trying to catch some of these kind of related ( ;-) ) issues at compile time, but then the static allocation would have been needed. Well , more or less.