To explain the problem in more detail… your pointer was pointing to an undefined memory address. The compiler rightly warned you about this, because when you start writing to a random memory address, a crash is the best you can hope for! In the later example, when you set the pointer to null, it was pointing at a memory address of zero. This will crash when you start writing to it, as you observed.
The pseudocode I wrote above will allocate memory for the struct on the stack and then return a copy of it to the calling code. There are ways to avoid the unnecessary memory copy, but these days the compiler will probably optimize that for you. And for such a small struct I wouldn’t worry about it.
However, you now need to take care to make sure the memory gets freed again once you’ve finished with it, otherwise you’ll have a memory leak.
To free the memory, you use the delete operator. For example:
// GetItemInfo dynamically allocates the Item Info (which i really don't recommend!)
FItemInfo* ItemInfo = GetItemInfo();
// Do some stuff with ItemInfo
...
// Release the memory
delete ItemInfo;
ItemInfo = nullptr;
Then you must not access the struct after that point.
Tbh I would strongly avoid using new/delete unless you are very confident in what you are doing. The potential for carnage is great! Unreal has some smart pointer classes that can help shield you from the lower-level memory management.
Another option is to construct the object outside the function and then pass it into your function (either by reference or by pointer) to be populated. For example:
But again I recommend only using pointers if you absolutely need to. Pointers have the potential to be null, or pointing at garbage. So if you’re not confident of the contents and lifetime of the memory being pointed at, then you’re going to have a bad time.