more robust free function