Using the first implementation of CreateData, you return a pointer to a variable with automatic storage duration and then use it past its lifetime, which is undefined behavior.
Less formally, what's actually happening is that data is allocated on the stack, and once you get around to using it as a, CreateData has ended and that stack space is now available for other functions to use, like main or printf, and those other functions are trampling over the space that was previously reserved for data.
When you use malloc, though, the memory is said to be allocated on the heap, not on the stack, and memory on the heap is only released when you tell it to be released (using free). Unlike with variables with automatic storage duration, the memory will not be released when CreateData has returned, so you can continue to use that memory in main.
strncpy()rather thanstrcpy(). See my rant onstrncpy().