3 ms·
I really wish we got cc: warning: UB line: 123 file: foo.c
by mzs 5y ago
I really wish we got
cc: warning: UB line: 123 file: foo.c
- gpderetta 5y agoCompilers will routinely warn if they can detect UB at compile time. The problem is that except in a few trivial cases it is impossible to detect UB at compile time. Even whole program static analysis can only catch a small subset.
- foxfluff 5y agoYeah, it'd be nice if we could solve the halting problem.
- tlb 5y agoYou can't detect most UB at compile time. LLVM has a system to detect it a runtime. There is a significant performance penalty, but it can be useful during testing. See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
- astrange 5y agoIt’s not actually that significant compared to something like asan. You can ship software with ubsan enabled if you want to.
- jcranmer 5y agoHow many warnings do you want for this small function? void oh_the_humanity(int *ptr, int val) { *ptr = val + 1; } Off the top of my head: * UB: ptr may be pointing a float variable. (It's not illegal to assign a float* to an int*, it's only UB when you actually dereference it with the wrong type.) * UB: val + 1 may overflow. * UB: potential data race on writing *ptr. * UB: ptr may be a one-past-the-end-of-the-array pointer, which can be validly constructed, but may not be dereferenced. * UB: ptr may be pointing to an object whose lifetime has expired. * UB: ptr may be uninitialized. * UB: val may be uninitialized. As you can see, UB is intensely specific to the actual data values; it's not really possible to catch even a large fraction of UB statically without severe false positive rates.
- mzs 5y agoYeah I know I get it, it's me more being wishful, but I more seriously wish at least compilers could emit a warning when they optimize something after UB: % cat foo.c #include <stdlib.h> int foo(int *bar) { int baz = *bar; if (bar == NULL) exit(2); return (baz); } % cc -O3 -Wall -Wextra -c foo.c % objdump -dr foo.o foo.o: file format Mach-O 64-bit x86-64 Disassembly of section __TEXT,__text: 0000000000000000 _foo: 0: 55 pushq %rbp 1: 48 89 e5 movq %rsp, %rbp 4: 8b 07 movl (%rdi), %eax 6: 5d popq %rbp 7: c3 retq % cc -O0 -Wall -Wextra -c foo.c % objdump -dr foo.o foo.o: file format Mach-O 64-bit x86-64 Disassembly of section __TEXT,__text: 0000000000000000 _foo: 0: 55 pushq %rbp 1: 48 89 e5 movq %rsp, %rbp 4: 48 83 ec 10 subq $16, %rsp 8: 48 89 7d f8 movq %rdi, -8(%rbp) c: 48 8b 45 f8 movq -8(%rbp), %rax 10: 8b 08 movl (%rax), %ecx 12: 89 4d f4 movl %ecx, -12(%rbp) 15: 48 83 7d f8 00 cmpq $0, -8(%rbp) 1a: 0f 85 0a 00 00 00 jne 10 <_foo+0x2a> 20: bf 02 00 00 00 movl $2, %edi 25: e8 00 00 00 00 callq 0 <_foo+0x2a> 0000000000000026: X86_64_RELOC_BRANCH _exit 2a: 8b 45 f4 movl -12(%rbp), %eax 2d: 48 83 c4 10 addq $16, %rsp 31: 5d popq %rbp 32: c3 retq % That's very similar to something that bit me in embedded except it was with pointer to structure. Compiler realizes I've derefed NULL and that's UB anyway so no need to do the NULL check later and merrily scribble exc vectors or whatever.
- foxfluff 5y agoThat's a nice example. It'd definitely be nice to have a warning for this one. Fwiw GCC does have a related warning flag (-Wnull-dereference) but I'm not sure it's made exactly for this. I believe it works based on functions being annotated for possibly returning NULL, e.g. malloc. It's also not enabled by -Wall or -W because apparently there were too many false positives: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96554 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96554 I imagine patches would be welcome. I'm guessing there are more people who like to wish for more compiler features than there are people who like to develop compilers :)
- deleted 5y ago[deleted]