The main problem with Free is multiple pointers to the same object. Yes, if you only have one pointer and the object goes out of scope, Free is fine. But if you don't like globals, you pass pointers around. You probably have a class somewhere that is the owner of that object, like that TStringList. You need to have one owner for each object instance, to decide who is going to Free it.
So, we have an object, with an owner, that hands out pointers to that object. Not to the pointer to that object it manages, but directly. If one of the parties that have one of those pointers free the object, all those pointers become invalid. FreeAndNil isn't going to help there, because it will only nil the pointer that is used to Free the object. And the only way to test if your pointer is still valid is accessing the object: if an access exception is raised, it wasn't. Lots of try .. except.
So, how do you fix that? Thaddy would say: if someone else than the owner frees it, you're doing it wrong. And pointers passed are one-use only: don't store them or pass them along! Which is fair enough, and doable if you're the only programmer. But it's not very bullet-proof.
A better option would be: hand out pointers to the pointer. That way, there is only one master pointer, which is dereferenced by the other pointers. FreeAndNil that, and you're done. This is the idea behind smart pointers.
You could also store all references to the object, possibly in a linked list that is part of TObject. Like reverse reference counting. On Free, you start by nilling all those pointers. This would require changing the compiler.
And lastly, garbage collection. Keep a list of all pointers used and nil the ones that pointed to that object after each Free. This is the brute-force method.