W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ living knowledge WWU Münster René Milk 15th October 2014
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 2 /19 Debugging Stages Coding Testing living knowledge Instrumentation WWU Münster Tools , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 3 /19 Bug prevention? ◮ defensive coding ◮ compile at high warning levels living knowledge WWU Münster , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 4 /19 Why you should compile at high warning levels Catch code segments that are valid C ++ , but (probably) not what you meant to write. ◮ typos ◮ unintentional operator usage ◮ potential data over/underflows living knowledge ◮ dead code WWU Münster , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 5 /19 Error free build � = error free code /// \file warnings_00.cc #include <cstddef> #include <string> 5 int main(int argn, char** argv) { auto name = argv[0]; int* i = 0; 10 unsigned long long bigstuff = 8 << 32; living knowledge if ( name == "foo" ) char* name = "bar"; else if ( name = NULL ) WWU Münster bigstuff = -1; 15 for ( ; bigstuff < 0; i++); bigstuff--; return bigstuff**i; } , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 6 /19 How many warnings did that generate? default “most" 6 13 Table : clang version 3.4-1 exp1 living knowledge ”most“ warnings settings WWU Münster clang++ -g -std=c++11 -Wsign-conversion -O0 -g -Wall -Wextra -Wc++0x-compat -Winline -pedantic -Wredundant-decls -Wloop-analysis -Wstring-compare -Wshadow -Wunused-variable -Wundef -Wnon-virtual-dtor -Wdocumentation -Wshorten-64-to-32 -Wused-but-marked-unused -Wdisabled-macro-expansion -Wparentheses -Wsometimes-uninitialized -Wconditional-uninitialized -Wfloat-equal -Wswitch-enum -Warray-bounds -Wcovered-switch-default -Wunreachable-code -Wnon-literal-null-conversion -Wtautological-compare , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 7 /19 sign-conversion / tautological-compare /// \file warnings_01.cc #include <cstddef> int main(int, char**) 5 { std::size_t bigstuff = -1; return bigstuff < 0; } warnings_01.cc:5:28: warning: implicit conversion changes signedness: ’int’ to living knowledge ’std::size_t’ (aka ’unsigned long’) [-Wsign-conversion] std::size_t bigstuff = -1; ~~~~~~~~ ^~ WWU Münster warnings_01.cc:6:21: warning: comparison of unsigned expression < 0 is always false [-Wtautological-compare] return bigstuff < 0; ~~~~~~~~ ^ ~ , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 8 /19 parentheses /// \file warnings_02.cc int main(int argn, char**) { if (argn = 1) 5 return -1; } warnings_02.cc:4:14: warning: using the result of an assignment as a condition without parentheses [-Wparentheses] if (argn = 1) ~~~~~^~~ living knowledge warnings_02.cc:4:14: note: place parentheses around the assignment to silence this warning if (argn = 1) WWU Münster ^ ( ) warnings_02.cc:4:14: note: use ’==’ to turn this assignment into an equality comparison if (argn = 1) ^ == , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 9 /19 loop-analysis / empty-body /// \file warnings_03.cc #include <iostream> int main(int argn, char** argv) 5 { for(;argn > 0;); std::cout << argv[--argn] << std::endl; } warnings_03.cc:6:10: warning: variable ’argn’ used in loop condition living knowledge not modified in loop body [-Wloop-analysis] for(;argn > 0;); ^~~~ WWU Münster warnings_03.cc:6:20: warning: for loop has empty body [-Wempty-body] for(;argn > 0;); ^ warnings_03.cc:6:20: note: put the semicolon on a separate line to silence this warning , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 10 /19 array-bounds /// \file warnings_06.cc const int ones[] = {1}; 5 int main() { const auto bar = ones[1]; return bar; } warnings_06.cc:4:22: warning: array index 1 is past the end of the array living knowledge (which contains 1 element) [-Warray-bounds] const auto bar = ones[1]; WWU Münster ^ ~ warnings_06.cc:1:1: note: array ’ones’ declared here const int ones[] = {1}; ^ , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 11 /19 Testing ◮ unit testing ◮ functional testing ◮ use a test harness! (i.e. gtest, Boost.Test) ◮ run tests as often as possible, automatically living knowledge WWU Münster , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 12 /19 Available sanitizers ◮ Address Sanitizer - out-of-bounds checks, use-after-free,... ◮ Thread Sanitizer - finds data races, deadlocks ◮ Memory Sanitizer - detects uninitialized reads ◮ Undefined Behavior Sanitizer - finds evaluations with undefined behavior living knowledge WWU Münster , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 13 /19 What is a sanitizer? ◮ inserts instrumentation code into the binary ◮ “replays” memory access in shadow memory ◮ runs algorithms to find patterns of unwanted behaviour ◮ incurs runtime and memory penalty when activated living knowledge WWU Münster , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 14 /19 Memory sanitizer - unitialized read int main(int argc, char**) { int* i = new int[666]; if (i[0]) 5 return -1; } ==14624== WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x7fdb3ee1b9e6 in main instrumentation_01.cc:6 living knowledge #1 0x7fdb3d9a3de4 in __libc_start_main /build/buildd/eglibc-2.17/csu/libc-start.c:260 #2 0x7fdb3ee1b89c in _start (01+0x6589c) WWU Münster SUMMARY: MemorySanitizer: use-of-uninitialized-value instrumentation_01.cc:6 main Exiting , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 15 /19 Address sanitizer - heap-use-after-free I #include <memory> #include <iostream> using namespace std; struct YYZ { 5 int length () const { return (4-int(radio_)*60)+25; } bool radio_; YYZ(bool radio = false) : radio_(radio){} }; 10 struct Player { const YYZ& song_; Player(const YYZ& song) : song_(song) {} int length() const { return song_.length(); } living knowledge }; 15 int main(int, char**) { WWU Münster unique_ptr<Player> player(nullptr); { YYZ* yyz = new YYZ; 20 player = unique_ptr<Player>(new Player(*yyz)); delete yyz; } auto le = player->length(); std::cout << le; 25 return le; } , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 16 /19 Heap-use-after-free II ================================================================= ==12704==ERROR: A6ddressSanitizer: heap-use-after-free on address 0x60200000eff0 at pc 0x473841 bp 0x7fff778bdcc0 sp 0x7fff778bdcb8 READ of size 1 at 0x60200000eff0 thread T0 #0 0x473840 in YYZ::length() const instrumentation_02.cc:5 #1 0x472f78 in main instrumentation_02.cc:23 #2 0x7f73aac68de4 in __libc_start_main /build/buildd/eglibc-2.17/csu/libc-start.c:260 #3 0x472dac in _start (02+0x472dac) 0x60200000eff0 is located 0 bytes inside of 1-byte region [0x60200000eff0,0x60200000eff1) freed by thread T0 here: #0 0x45eb29 in operator delete(void*) (02+0x45eb29) living knowledge #1 0x472f68 in main instrumentation_02.cc:21 #2 0x7f73aac68de4 in __libc_start_main /build/buildd/eglibc-2.17/csu/libc-start.c:260 WWU Münster previously allocated by thread T0 here: #0 0x45e829 in operator new(unsigned long) (02+0x45e829) #1 0x472f12 in main instrumentation_02.cc:19 #2 0x7f73aac68de4 in __libc_start_main /build/buildd/eglibc-2.17/csu/libc-start.c:260 SUMMARY: AddressSanitizer: heap-use-after-free instrumentation_02.cc:5 YYZ::length() const , , rene.milk@wwu.de
W ESTFÄLISCHE W ILHELMS -U NIVERSITÄT M ÜNSTER Debugging C ++ 17 /19 Heap-use-after-free III Shadow bytes around the buggy address: 0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c047fff9df0: fa fa fa fa fa fa fa fa fa fa 00 fa fa fa[fd]fa 0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 living knowledge Heap left redzone: fa Heap right redzone: fb Freed heap region: fd WWU Münster Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 ASan internal: fe ==12704==ABORTING , , rene.milk@wwu.de
Recommend
More recommend