Know who is owner of that memory.
- create objects on stack as much as possible (no useless new)
- Avoid transfer of ownership unless really needed
- Use RAII and smart pointers
- If transfer of ownership is mandated (without smart pointers), then, document clearly the code (the functions should have a non-ambiguous name, always using the same name pattern, like "char * allocateMyString()" and "void deallocateMyString(char * p)".
How it clearly facilitates safer code, which minimizes the risk of enigmatic bugs, which increases maintainability, etc.?
Not having a clear memory ownership philosophy leads to interesting bugs or memory leaks, and time lost wondering if the char * returned by this function should be deallocated by the user, or not, or given back to a special deallocation function, etc..
As much as possible, the function/object allocating the memory must be the function/object deallocating it.