There is a problem with dangling pointers. See kern_exit.c:
* s_ttyp is not zero'd; we use this to indicate
* that the session once had a controlling terminal.
* (for logging and informational purposes)
and some things follow the pointer for closed devices. Perhaps only
applications like ptstat -t. pstat also wants to work with an array of
Digital UNIX had the same misfeature. Which is why it now uses
a vnode reference:
struct vnode *s_ttyvp; /* vnode of controlling terminal */
This also allows other things than classic ttys to be controlling
terminals (say streams devices or portals or ...).
The same problems interfere with dynamic allocation of tty structs for
hardware ttys, but there is less to be gained by dynamic allocation in
this case. The closed tty structs are a good place for holding statstics
and the state for the next open (they don't actually hold much of it now).