Not to mention tracepoints (logging breakpoints), which are functionally the same as printf but don't require compiling/restarting.