5 ms·
I often use printf for debugging. An unexpectedly NULL string is exactly the sort of thing I want it to help me debug!
by millstone 11y ago
I often use printf for debugging. An unexpectedly NULL string is exactly the sort of thing I want it to help me debug!
- cperciva 11y agoCrashing works just as well as printing "(null)" for that purpose. Possibly even better, since you'll have a core dump. ;-)
- millstone 11y agoSometimes it does, but often it does not: printf("name: %s %s", first, last); If it crashes, there's no easy way to know which one was NULL!
- cperciva 11y agoTell your debugger to open the core dump and print the two pointers. ;-)
- SomeCallMeTim 11y agoJust try that when debugging an app on an embedded system, mobile, or a console, where you have access to the console but no core dump. Sorry, but I agree with all the folks who say printf (and similar) is categorically more useful when it prints "(null)". I've had many obscure crashes on systems that were precisely because a logging printf in a seldom-tested piece of code had a parameter that sometimes was correctly null would crash it out. If the debugger isn't attached and we just have a crash dump we can't read (happens even on platforms where you're SUPPOSED to be able to read them), then we have to attach the debugger and hope that we can reproduce the obscure state that caused the crash. Anything that makes debugging statements more robust and less crash-prone is a good thing. End of story. As others have said, if you want something to verify that a pointer is non-null, use an assert().
- cperciva 11y agoAs others have said, if you want something to verify that a pointer is non-null, use an assert(). I said that, too. But sometimes developers don't think to put in every possible assert. Having the C library explode violently when it detects a bug in their code even when they forgot to include an assert which checks for that bug will help to find bugs under such circumstances.
- kazinator 11y agoIn the environment under question, you do not need an assert. You just have to dereference the pointer. Unless the pointer is displaced past the unmapped page zero (i.e you're accessing str[4096] and above, and not touching str[0] through str[4095] on a system with 4K pages) you will get a fault resulting in a fatal signal: SIGSEGV. Whereas an assertion will get you a SIGABRT, but the result is the same. The assertion will be earlier, that's all, before you try to dereference the pointer. Probably not much earlier. Environments that do not have the hardware-assisted detection for null dereferences can still be targetted by a compiler which generates code which does the check on pointer dereference. That can be included in your debug builds, or even left in production builds if the performance impact is acceptable. I seem remember that some compilers for the Intel 8088 MS-DOS environment had a code generation option for trapping nulls.
- SomeCallMeTim 11y ago>will help to find bugs under such circumstances. Will help to crash your code when you use printf, which (in game development in particular) is 99% for debugging statements. No, having the C library explode violently at any opportunity does not always help detect bugs, and can be 100% harmful. You're overgeneralizing your own bug circumstances and development environment. That said, if it matters that much to you, wrap printf with a modified version that asserts on NULL-ish pointer dereferences. Don't attempt to roll back the clock on library development for everyone.
- kazinator 11y agoCrashing can interefere with the debugging session. You have the program stopped at a breakpoint and tell gdb to run some function inside the program which prints something with printf. Oops, that function blows up! The whole thing is foobared now; you've injected a fatal signal into the program that wasn't there.
- nitrogen 11y agoA note for those encountering difficulty: most people will have to type ulimit -c unlimited to get core dumps. $ echo 'int main(void){ return *(int*)0; }' > crash.c $ gcc -Wall -Wextra -std=c1x crash.c -o crash $ ./crash Segmentation fault $ ulimit -c unlimited $ ./crash Segmentation fault (core dumped)
- x0x0 11y agofprintf(stderr, "test %s\n", s != NULL ? s : "NULL"); if(s == NULL) abort();