Unfortunately, not all languages/systems have an efficient and useful debugger. This becomes especially true when multiple stacks are involved. But the print statement remains possible across almost all tools, technologies and systems
Another use case for printf debugging is occasional or transient issues where there is a bug, but it only presents in an aggregate of many runs (or a lot of runtime).
I debug scientific simulations in this way with printf's, because I need to look across 100 log files to find 2 or 3 instances of a bug.
Then I can reproduce it and zoom in on the exact problem with either more logging or a debugger.