The idea: copying a struct copies pointers, not what they point to
*c = *d is a shallow copy: the two char * fields are copied, so the clone and the original now point to the same strings. Each of them thinks it owns those strings. Each frees them. The second free is a double free.
The rule that prevents it: a pointer that gets freed must have exactly one owner.
The situation
doc_clone must return a fully independent document: changing or freeing one must never affect the other.
Your mission
Run the sanitizer. Depending on which line runs first it reports a double free or a use-after-free, and either way it names where the block was allocated and where it was first freed. Use that to tell the junior what doc_clone must do so that each Doc owns private strings.
What to watch for
- "Just don't free it twice" is not a design. Freeing less leaks, and the sharing is still there.
- Look at how
doc_newcreates its strings. The clone must do the same.