Typically the memory manager keeps track of malloc'ed memory by storing the pointer in a table and when free or realloc, etc. are called, it looks up the pointer in its table so the the value of the actual pointer is the lookup key. So, with respect to the first part of your post, yes, you can free the pointer returned by the function since its value is the same.

In the second case, you are reassigning your pointer to a different location and therefore the memory allocated by p is left dangling with no way to free it.