sort_stats wraps the specific sort helpers in try/except and falls back to
cpu_percent for the whole list. _sort_cpu_times indexed cpu_times['user'] and
_sort_io_counters indexed io_counters[0..3], so one row with an empty value
raised and silently reordered every other row while the header still read TIME
or IOR/IOW.
Those empty values are expected rather than corrupt: programs.py builds a
program with p['cpu_times'] or {} and list(p['io_counters'] or NO_IO_COUNTERS),
and its own comment says some values can be None on macOS system processes.
Each helper now reads a missing value as zero, so the degenerate row sorts last
and the rest keep their order.