Один из способов поймать некоторые из этих вещей по своему усмотрению - сделать так, чтобы точка всегда обнуляла любой указатель, который вы освободили, чтобы у него никогда не было длительной ссылки.
Node* freeSubtree(Node *N) { if(!N) return;
freeSubtree(N->left);
free(N); N = NULL; // NULL out the pointer!
freeSubtree(N->right);
}
иконечно @Johnny Mopp указал на реальную ошибку, которая требует от вас переместить free()
в конец.
На практике для такого кода я становлюсь еще более агрессивным в C с любой функцией, которая может освободитьпамяти, передавая адрес указателя, так что сам адрес может быть обнулен в вызывающей стороне .
Node *freeSubtree(Node **PN)
{
if (!PN || !*PN) return;
freeSubtree( &( (*PN)->left) ); // frees and NULLs the ->left pointer
freeSubtree( &( (*PN)->right) ); // frees and NULLs the ->right pointer
free(*PN);
*PN = NULL; // NULL the *caller's* handle on the pointer
}
Если вы хотите использовать эту технику, выдействительно нужно идти ва-банк, потому что параметр address-of-pointer обычно получает довольно широкое распространение, но это удача - никогда не иметь ошибок, связанных с использованием после освобождения.
Редактировать: ошибки с использованием после освобожденияне всегда просто ошибки, иногда они ошибки безопасности ошибки.
Примечание: в C ++ вы можете использовать параметры ref, чтобы сделать это гораздо более читабельно.