Write better* C++ - Amazon Simple Storage Service · Write better* C++ with help from your friend...
Transcript of Write better* C++ - Amazon Simple Storage Service · Write better* C++ with help from your friend...
Write better* C++with help from your friend Clang
René Milk 23rd October 2013living knowledgeWWU Münster
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 2 /31
Contents
What is Clang?
Static analysis
Dynamic analysis (sanitizers)
Tools
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 3 /31
LLVM1
LLVM (formerly Low Level Virtual Machine) is a compiler infrastructure written in C++; it isdesigned for compile-time, link-time, run-time, and "idle-time" optimization of programswritten in arbitrary programming languages.
Clang2
Clang is a compiler front end for the C, C++, Objective-C and Objective-C++ programminglanguages. It uses LLVM as its back end and has been part of its releases since LLVM 2.6.
1https://en.wikipedia.org/wiki/LLVM2https://en.wikipedia.org/wiki/Clang
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 4 /31
Clang features
I fast compiles with low memory usage 3
I detailed “fix-it” notes for warnings and errorsI build on top of libclang, API allows for extensive toolingI fully4 supports c++11 since version 3.3
3http://clang.llvm.org/features.html#performance4http://clang.llvm.org/cxx_status.html
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 5 /31
for this talk we’ll take “better” as referring to:
I code with fewer bugsI shorter compile timesI consistent formattingI not faster executionI not code quality in terms of style, complexity, etc.
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 6 /31
static code (program) analysis5
Static program analysis is the analysis of computer software that is performed withoutactually executing programs (analysis performed on executing programs is known asdynamic analysis).
5https://en.wikipedia.org/wiki/Static_program_analysis
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 7 /31
Why you should compile at high warning levels
Catch code segments that are valid C++, but (probably) not what you meant to write.I typosI unintentional operator usageI potential data over/underflowsI dead code
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 8 /31
error free build 6= error free code
/// \file warnings_00.cc
#include <cstddef>#include <string>
5int main(int argn, char** argv){
auto name = argv[0];int* i = 0;
10 unsigned long long bigstuff = 8 << 32;if ( name == "foo" )
char* name = "bar";else if ( name = NULL )
bigstuff = -1;15 for ( ; bigstuff < 0; i++);
bigstuff--;return bigstuff**i;
}
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 9 /31
how many warnings did that generate?
default “most"
6 13
Table : clang version 3.4-1 exp1
”most“ warnings settingsclang++ -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
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 10 /31
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’std::size_t’ (aka ’unsigned long’) [-Wsign-conversion]
std::size_t bigstuff = -1;~~~~~~~~ ^~
warnings_01.cc:6:21: warning: comparison of unsigned expression < 0 is alwaysfalse [-Wtautological-compare]
return bigstuff < 0;~~~~~~~~ ^ ~
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 11 /31
parentheses
/// \file warnings_02.ccint main(int argn, char**){
if (argn = 1)5 return -1;
}
warnings_02.cc:4:14: warning: using the result of an assignment asa condition without parentheses [-Wparentheses]
if (argn = 1)~~~~~^~~
warnings_02.cc:4:14: note: place parentheses around the assignment to silence this warningif (argn = 1)
^( )
warnings_02.cc:4:14: note: use ’==’ to turn this assignment into an equality comparisonif (argn = 1)
^==
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 12 /31
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 conditionnot modified in loop body [-Wloop-analysis]
for(;argn > 0;);^~~~
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
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 13 /31
switch / return-type
/// \file warnings_04.cc
enum Things { Dog, Frog };
5 int foo(Things thing) {switch (thing) {
case Dog: return 9001;}
}10
int main(int, char**) { return 0;}
warnings_04.cc:6:13: warning: enumeration value ’Frog’ not handled in switch [-Wswitch]switch (thing) {
^warnings_04.cc:9:1: warning: control may reach end of non-void function [-Wreturn-type]}^
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 14 /31
covered-switch-default
/// \file warnings_05.cc
enum Things { Dog, Frog };
5 int bar(Things thing) {int ret;switch (thing) {
case Dog: case Frog: ret = 0;default: ret = -1;
10 }return ret;
}
int main(int, char**) { return 0;}
warnings_05.cc:9:9: warning: default label in switch which coversall enumeration values [-Wcovered-switch-default]
default: ret = -1;^
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 15 /31
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(which contains 1 element) [-Warray-bounds]
const auto bar = ones[1];^ ~
warnings_06.cc:1:1: note: array ’ones’ declared hereconst int ones[] = {1};^
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 16 /31
the analyzer plugin
#include <cstddef>#include <string>
inline int the_meaning_of_life_and_everything() { return 42; }5 int main(int, char**)
{const int* i = nullptr;auto j = the_meaning_of_life_and_everything();j = sizeof(int);
10 return j+*i;}
static_00.cc:8:10: warning: Value stored to ’j’ during its initialization is never readauto j = the_meaning_of_life_and_everything();
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~static_00.cc:10:14: warning: Dereference of null pointer (loaded from variable ’i’)
return j+*i;^~
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 17 /31
available sanitizers
I Address Sanitizer - out-of-bounds checks, use-after-free,...I Thread Sanitizer - finds data racesI Memory Sanitizer - detects uninitialized readsI (soon?) Undefined Behavior Sanitizer - ???
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 18 /31
What is a sanitizer?
I inserts instrumentation code into the binaryI “replays” memory access in shadow memoryI runs algorithms to find patterns of unwanted behaviourI incurs runtime and memory penalty when activated
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 19 /31
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#1 0x7fdb3d9a3de4 in __libc_start_main /build/buildd/eglibc-2.17/csu/libc-start.c:260#2 0x7fdb3ee1b89c in _start (01+0x6589c)
SUMMARY: MemorySanitizer: use-of-uninitialized-value instrumentation_01.cc:6 mainExiting
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 20 /31
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(); }
};15 int main(int, char**)
{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;}
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 21 /31
heap-use-after-free II
===================================================================12704==ERROR: A6ddressSanitizer: heap-use-after-free on address 0x60200000eff0
at pc 0x473841 bp 0x7fff778bdcc0 sp 0x7fff778bdcb8READ 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)#1 0x472f68 in main instrumentation_02.cc:21#2 0x7f73aac68de4 in __libc_start_main /build/buildd/eglibc-2.17/csu/libc-start.c:260
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
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 22 /31
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 fa0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff9de0: 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]fa0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa0x0c047fff9e40: 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: 00Partially addressable: 01 02 03 04 05 06 07Heap left redzone: faHeap right redzone: fbFreed heap region: fdStack left redzone: f1Stack mid redzone: f2Stack right redzone: f3Stack partial redzone: f4Stack after return: f5Stack use after scope: f8Global redzone: f9Global init order: f6Poisoned by user: f7ASan internal: fe
==12704==ABORTING
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 23 /31
Tools built with (lib)Clang
I clang-formatI clang-modernizeI include-what-you-use (iwyu)I cldoc
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 24 /31
Example clang-format (before)
/// \file format.cc#include <cstddef>#include <string>int main(int argn,char** argv){auto name=argv[0];int* i=0;unsigned long
5 long bigstuff=8<<32;if(name=="foo")char* name="bar";else if(name=NULL)bigstuff=-1;for(;bigstuff<0;i++);bigstuff--;return bigstuff**i;}
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 25 /31
Example clang-format (after)
clang-format-3.4 -style=LLVM format.cc > format_after.cc/// \file format.cc#include <cstddef>#include <string>int main(int argn, char **argv) {
5 auto name = argv[0];int *i = 0;unsigned long long bigstuff = 8 << 32;if (name == "foo")
char *name = "bar";10 else if (name = NULL)
bigstuff = -1;for (; bigstuff < 0; i++)
;bigstuff--;
15 return bigstuff * *i;}
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 26 /31
Example clang-modernize (before)
/// \file modernize.cc#include <vector>
template <class T>5 void increment(std::vector<T>& vec) {
for (typename std::vector<T>::iterator it = vec.begin();it != vec.end(); ++it)
{++(*it);
10 }}
int main() {std::vector<int> a(2,4); increment(a);}
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 27 /31
Example clang-modernize (after)
clang-modernize -format-style=LLVM modernize.cc/// \file modernize.cc#include <vector>
template <class T>5 void increment(std::vector<T>& vec) {
for (auto &elem : vec) {++(elem);}
}10
int main() {std::vector<int> a(2,4); increment(a);}
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 28 /31
Example iwyu (input)
/// \file iwyu.cc
#include <vector>#include <assert.h>
5 #include <iterator>#include <memory>#include <sstream>#include <iostream>
10 int main(){
using namespace std;cout << abs(long(-1));
}
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 29 /31
Example iwyu (output)
iwyu -std=c++11 iwyu.cciwyu.cc should add these lines:#include <cstdlib> // for abs
iwyu.cc should remove these lines:5 - #include <assert.h> // lines 2-2
- #include <iterator> // lines 3-3- #include <memory> // lines 4-4- #include <sstream> // lines 5-5- #include <vector> // lines 1-1
10The full include-list for iwyu.cc:#include <cstdlib> // for abs#include <iostream> // for cout, ostream---
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 30 /31
Example cldoc
http://jessevdk.github.io/cldoc/example/
,,
livin
gkn
owle
dge
WW
UM
ünst
er
WESTFÄLISCHEWILHELMS-UNIVERSITÄTMÜNSTER Write better* C++ 31 /31
Thank you foryour attention.
,,