Professional Documents
Culture Documents
Steve Oualline
Page 1
Steve Oualline
Copyright 2008, Steve Oualline !his "ork is licensed under the Creative Co##ons $icense "hich appears in %ppendi& ' (ou are )ree*
to Share + to copy, distri,ute, display, and per)or# the "ork to -e#i& + to #ake derivative "orks
%ttri,ution* (ou #ust attri,ute the "ork ,y identi)ying those portions o) the ,ook you use as /.sed ,y per#ission o) Steve Oualline 0http*11""" oualline co#2 under the the Creative Co##ons $icense 3 0!he attri,ution should not in any "ay that suggests that Steve Oualilne endorses you or your use o) the "ork2 'or any reuse or distri,ution, you #ust #ake clear to others the license ter#s o) this "ork !he ,est "ay to do this is "ith a link to the "e, page* http*11creativeco##ons org1licenses1,y14 01us1 %ny o) the a,ove conditions can ,e "aived i) you get per#ission )ro# Steve Oualline %part )ro# the re#i& rights granted under this license, nothing in this license i#pairs or restricts the author5s #oral rights
Page 2
Steve Oualline
Table of Contents
-eal 6orld Hacks 7 Hack 1* 8ake Code 9isappear 10 Hack 2* $et So#eone :lse 6rite ;t 12 Hack 4* .se the const <ey"ord 're=uently 'or 8a&i#u# Protection 12 Hack >* !urn large para#eter lists into structures 1> Hack ?* 9e)ining @its 1A Hack A* .se @it )ields Care)ully 18 Hack B* 9ocu#enting ,it#apped varia,les 17 Hack 8* Creating a class "hich can not ,e copied 21 Hack 7* Creating Sel)Cregistering Classes 22 Hack 10* 9ecouple the ;nter)ace and the ;#ple#entation 2? Hack 11* $earning 'ro# !he $inu& <ernel $ist 'unctions 2B Hack 12* :li#inate Side :))ects 27 Hack 14* 9on5t Put %ssign#ent State#ents ;nside %ny Other State#ents 40 Hack 1>* .se const ;nstead o) Dde)ine 6hen Possi,le 41 Hack 1?* ;) (ou 8ust .se Dde)ine Put Parenthesis %round !he Ealue 42 Hack 1A* .se inline 'unctions ;nstead o) Para#eteriFed 8acros 6henever Possi,le 44 Hack 1B* ;) (ou 8ust .se Para#eteriFed 8acros Put Parenthesis %round !he argu#ents 4> Hack 18* 9on5t 6rite %#,iguous Code 4> Hack 17* 9on5t @e Clever 6ith the Precedence -ules 4? Hack 20* ;nclude (our O"n Header 'ile 4A Hack 21* SynchroniFe Header and Code 'ile Ga#es 4B Hack 22* Gever !rust .ser ;nput 48 Hack 24* 9on5t use gets >0 Hack 2>* 'lush 9e,ugging >1 Hack 2?* Protect array accesses "ith assert >2 Hack 2A* .se a !e#plate to Create Sa)e %rrays >? Hack 2B* 6hen 9oing Gothing, @e O,vious %,out ;t >A Hack 28* :nd :very Case "ith ,reak or 1H 'all !hrough H1 >B Hack 27* % Si#ple assert State#ents 'or ;#possi,le Conditions >B Hack 40* %l"ays Check )or !he ;#possi,le Cases ;n s"itches >8 Hack 41* Create Opa=ue !ypes 0Handles2 6hich can ,e Checked at Co#pile !i#e >7 Hack 42* .sing siFeo) 6hen Ieroing Out %rrays ?1 Hack 44* .se siFeo)0var2 ;nstead o) siFeo)0type2 in #e#set Calls ?1 Hack 4>* Iero Out Pointers to %void -euse ?4 Hack 4?* .se strncpy ;nstead o) strcpy !o %void @u))er Over)lo"s ?> Hack 4A* .se strncat instead o) strcat )or sa)ety ?? Page 4 Copyright 2008, Steve Oualline
Steve Oualline
Hack 4B* .se snprint) !o Create Strings ?A Hack 48* 9on5t 9esign in %rti)icial $i#its ?B Hack 47* %l"ays Check )or Sel) %ssign#ent ?8 Hack >0* .se Sentinels to Protect the ;ntegrity o) (our Classes A0 Hack >1* Solve 8e#ory Pro,le#s "ith valgrind A1 Hack >2* 'inding .ninitialiFed Earia,les A4 Hack 27* Ealgrind Pronunciation A? Hack >4* $ocating Pointer pro,le#s :lectric'ence A? Hack >>* 9ealing "ith Co#ple& 'unction and Pointer 9eclarations A? Hack >?* Create !e&t 'iles ;nstead o) @inary Ones 6henever 'easi,le AB Hack >A* .se 8agic Strings to ;denti)y 'ile !ypes A7 Hack >B* .se 8agic Gu#,ers )or @inary 'iles A7 Hack >8* %uto#atic @yte Ordering !hrough 8agic Gu#,ers B0 Hack >7* 6riting Porta,le @inary 'iles B1 Hack ?0* 8ake (ou @inary 'iles :&tensi,le B2 Hack ?1* .se #agic nu#,ers to protect ,inary )ile records B> Hack ?2* <no" 6hen to .se Je&it BA Hack ?4* 8ark te#porary de,ugging #essages "ith a special set o) characters B8 Hack ?>* .se the :ditor to %nalyFe $og Output B8 Hack ??* 'le&i,le $ogging B7 Hack ?A* !urn 9e,ugging On and O)) 6ith a Signal 81 Hack ?B* .se a Signal 'ile to !urn On and O)) 9e,ugging 82 Hack ?8* Starting the 9e,ugger %uto#atically .pon :rror 82 Hack ?7* 8aking assert 'ailures Start the 9e,ugger 88 Hack A0* Stopping the Progra# at the -ight Place 70 Hack A1* Creating Headings "ithin Co##ent 72 Hack A2* :#phasiFing "ords "ithin a paragraph 74 Hack A4* Putting 9ra"ings ;n Co##ents 74 Hack A>* Providing .ser 9ocu#entation 7> Hack A?* 9ocu#enting the %P; 7A Hack AA* .se the $inu& Cross -e)erence to Gavigate $arge Coding ProKects 77 Hack AB* .sing the PreCprocessor to Generate Ga#e $ists 104 Hack A8* Creating 6ord $ists %uto#atically 10> Hack A7* Preventing 9ou,le ;nclusion o) Header 'iles 10? Hack B0* :nclose 8ultiple $ine 8acros ;n do1"hile 10? Hack B1* .se Di) 0 to -e#ove Code 10B Hack B2* .se Di)nde) LLL to ;denti)y !e#porary Code 10B Hack B4* .se Di)de) on the 'unction Got on the 'unction Call to :li#inate :&cess Di)de)s 108 Hack B>* Create Code to Help :li#inate Di)de) State#ents 'ro# 'unction @odies 107 Hack B?* 9on5t .se any /6ell <no"n3 Speedups 6ithout Eeri)ication 112 Hack BA* .se g#ake CK to speed up co#pilation on dual processor #achines Page > Copyright 2008, Steve Oualline
Steve Oualline
11? Hack BB* %void -eco#piling ,y .sing ccache 11B Hack B8* .sing ccache 6ithout Changing %ll (our 8ake)iles 118 Hack B7* 9istri,ute the 6orkload 6ith distcc 117 Hack 80* 9on5t Opti#iFe .nless (ou -eally Geed to 120 Hack 81* .se the Pro)iler to $ocate Places to Opti#iFe 120 Hack 82* %void the 'or#atted Output 'unctions 122 Hack 84* .se ++& ;nstead o) &++ @ecause ;t5s 'aster 124 Hack 8>* Opti#iFe ;1O ,y .sing the C ;1O %P; ;nstead o) the C++ One 12> Hack 8?* .se a $ocal Cache to %void -eco#puting the Sa#e -esult 12A Hack 8A* .se a Custo# ne"1delete to Speed 9yna#ic Storage %llocation 128 %ntiCHack 8B* Creating a Custo#iFed ne" 1 delete .nnecessarily 127 %ntiCHack 88* .sing shi)t to #ultiple or divide ,y po"ers o) 2 140 Hack 87* .se static inline ;nstead o) inline !o Save Space 141 Hack 70* .se dou,le ;nstead o) 'loat 'aster Operations 6hen (ou 9on5t Have % 'loating Point Processor 142 Hack 71* !ell the Co#piler to @reak the Standard and 'orce it !o !reat )loat as )loat 6hen 9oing %rith#etic 144 Hack 72* 'i&ed point arith#etic 14> Hack 74* Eeri)y Opti#iFed Code %gainst the .nopti#iFed Eersion 148 Case Study* Opti#iFing ,itsJtoJ,ytes 147 Hack 7>* 9esignated Structure ;nitialiFers 1>> Hack 7?* Checking print) style %rgu#ents $ists 1>? Hack 7A* Packing structures 1>A Hack 7B* Creating 'unctions 6ho5s -eturn Shouldn5t @e ;gnored 1>A Hack 78* Creating 'unctions 6hich Gever -eturn 1>B Hack 77* .sing the GCC Heap 8e#ory Checking 'unctions to $ocate :rrors 1>7 Hack 100* !racing 8e#ory .sage 1?0 Hack 101* Generating a @acktrace 1?2 %ntiCHack 102* .sing /Dde)ine e&tern3 )or Earia,le 9eclarations 1?A %ntiCHack 104* .se , 0co##a2 to Koin state#ents 1?8 %ntiCHack 10>* i) 0strc#p0a,,22 1?7 %ntiCHack 10?* i) 0ptr2 1A1 %ntiCHack 10A* !he /"hile 00ch M getch022 NM :O'23 Hack 1A1 %ntiCHack 10B* .sing Dde)ine to %ug#ent the C++ Synta& 1A4 %ntiCHack 108* .sing @:G;G and :G9 ;nstead o) O and P 1A4 %ntiCHack 107* Earia,le %rgu#ent $ists 1A> %ntiCHack 110* Opa=ue Handles 1AA %ntiCHack 111* 8icroso)t 0Hungarian2 Gotation 1AA Hack 112* %l"ays Eeri)y the Hard"are Speci)ication 1B0 Hack 114* .se Porta,le !ypes 6hich Speci)y :&actly Ho" 6ide (our ;ntegers %re 1B1 Hack 11>* Eeri)y Structure SiFes 1B2 Page ? Copyright 2008, Steve Oualline
Steve Oualline
Hack 11?* Eeri)y O))sets 6hen 9e)ining the Hard"are ;nter)ace 1B> Hack 11A* Pack Structures !o :li#inate Hidden Padding 1B> Hack 11B* .nderstand 6hat the <ey"ord volatile 9oes and Ho" to .se ;t 1B? Hack 118* .nderstand 6hat the Opti#iFer Can 9o !o (ou 1BB Hack 117* ;n :#,edded Progra#s, !ry !o Handle :rrors 6ithout Stopping 180 Hack 120* 9etecting Starvation 182 Hack 121* !urning on Synta& Coloring 18? Hack 122* .sing Ei#5s internal #ake syste# 18? Hack 124* %uto#atically ;ndenting Code 188 Hack 12>* ;ndenting :&isting @locks o) Code 188 Hack 12?* .se tags to Gavigate the Code 170 Hack 12A* (ou Geed to 'ind the $ocation o) Procedure )or 6hich (ou Only <no" Part o) the Ga#e 17> Hack 12B* .se *vi#grep to Search )or Earia,les or 'unctions 17A Hack 128* Eie"ing the $ogic o) $arge 'unctions 17B Hack 127* Eie" $og)iles "ith Ei# 177 Hack 140* 'lipping a Earia,le @et"een 1 and 2 201 Hack 141* S"apping !"o Gu#,ers 6ithout a !e#porary 202 Hack 142* -eversing the 6ords ;n a String 6ithout a !e#porary 20> Hack 144* ;#ple#enting a 9ou,le $inked $ist "ith a Single Pointer 20A Hack 14>* %ccessing Shared 8e#ory 6ithout a $ock 20B Hack 14?* %ns"ering the O,Kect Oriented Challenge 207 %ppendi& %* Hacker Luotes Grace Hopper $inu& !orvals %ppendi& @* (ou <no" (ou5re a Hacker ;) %ppendi& C* Hacking Sins .sing the letters O, l, ; as varia,le na#es Got Sharing (our 6ork Go Co##ents ;ncOnsis!enc( 9uplicating Code 0Progra##ing ,y Cut and Paste2 %ppendi& 9* Open Source !ools 'or Hackers ctags Q 'unction ;nde&ing Syste# do&ygen 'la"'inder gcc Q !he GG. C and C++ co#piler suite l&r 218 Perl 0)or perldoc and related tools2 Q 9ocu#entation Syste# valgrind 0#e#ory checking tools2 Ei# 0Ei ;#proved2 Page A 211 211 212 21> 21A 21A 21A 21A 21A 21B 218 218 218 218 218 217 217 217
C++ Hackers Guide %ppendi& :* Sa)e 9esign Patterns %ppendi& '* Creative Co##ons $icense $icense Creative Co##ons Gotice
Page B
Steve Oualline
Preface
Originally ter# hacker #eant so#eone "ho did the i#possi,le "ith very little resources and #uch skill !he ,asic de)inition is /so#eone "ho #akes )ine )urniture "ith an a&e3 Hackers "ere the people "ho kne" the co#puter inside and out and "ho could per)or# cool, clever, and i#possi,le )eats "ith their co#puters Go" days the ter# has ,een corrupted to #ean so#eone "ho ,reaks into co#puters, ,ut in this ,ook "e use hacker in its original honora,le )or# 8y )irst introduction to true hackers "as "hen ; Koined the 8idnight Co#puter Clu, "hen ; "ent to college !his "asn5t an o))icial clu,, Kust a group o) people "ho hung out in the P9PC8 la, a)ter #idnight to progra# and discuss co#puters ; re#e#,er one )ello" "ho had taken R10 o) parts )ro# -adio Shack and created a little ,lack ,o& "hich he could use "ith an oscilloscope to align 9:C!ape drives 9:C at the ti#e needed a R4?,000 custo# ,uilt #achine to do the sa#e thing !here "ere also so#e people there "ho enKoyed progra##ing the P9PC8 to play #usic !his "as kind o) hard to do since the #achine didn5t have a sound card @ut so#eone discovered that i) you put a radio near the #achine the inter)erence could ,e heard on the speaker %)ter playing around "ith the syste# )or a "hile people discovered ho" to generate tones using the inter)erence and thus 8.S;CC8 progra##ing syste# "as ,orn So that the syste# didn5t have a sound card didn5t stop hackers )ro# getting sound out o) it !his illustrates one o) the attri,utes o) great hacks, doing the /i#possi,le3 "ith totally inade=uate resources 8y )irst real hack occurred "hen so#e )riends o) #ine "ere taking asse#,ly language !heir Ko, "as to "rite a )unction to do a #atri& #ultiply ; sho"ed the# ho" to use the P9PC105s a,ility to do dou,le indirect inde&ed addressing1 "hich cut do"n the a#ount o) "ork needed to access an ele#ent o) the #atri& )ro# one #ultiply per ele#ent to one #ultiply per #atri& !he pro)essor "ho taught the asse#,ly class )elt that the only reason you5d ever "ant to progra# in asse#,ly is )or speed, so he ti#ed the ho#e"ork and co#pared the results against his /opti#al3 solution :very once in a "hile he5d )ind a progra# that "as slightly )aster, ,ut he "as a good progra##er so people rarely ,eat hi#
1 !he only #achines ; kno" o) "ith this strange addressing #ode "ere the P9PC10 and P9PC20 !he closest you can co#e this hack on today5s #achines involves vectoriFing the #atri&
Page 8
Steve Oualline
:&cept "hen it ca#e to #y )riends5 #atri& #ultiply assign#ent !he slo"est ca#e in at ten ti#es )aster than his /opti#al3 solution !he )astest "as so )ast that it ,roke the ti#ing tools he "as using He had to ad#it it "as a neat hack 0%)ter seeing this very strange code, he did so#ething very unusual )or a pro)essor* he called #y )riends to the )ront o) the class, gave the# the chalk and had the# teach hi# 2 6hat #akes a good hackS ;t involves go over, around, or through the li#itations i#posed ,y the #achine, the co#piler, #anage#ent, security2 or any thing else !rue hackers develop tricks and techni=ues designed to overco#e the o,stacles in )ront o) the# and to i#prove the =uality o) the syste#s they "ork "ith !hese are the true hacks !his ,ook contains a collection o) hacks ,orn out o) over )orty years o) progra##ing e&perience Here you5ll )ind all sorts o) hacks to #ake your progra#s #ore relia,le, #ore reada,le, and easier to de,ug ;n the true hacker tradition, this is the result o) o,serving "hat "orks and ho" it "orks, i#proving the syste#, and then passing the in)or#ation on
2 !rue hackers only ,reak security to discover "eaknesses in the syste# or to #ake i#prove#ents that the current security policy doesn5t allo" the# to do !hey don5t ,reak into so they can steal, copy protected in)or#ation, or spy on other people
Page 7
Steve Oualline
Page 10
Steve Oualline
8y Ko, "as to translate these 4B pieces o) code )ro# one language to another ;nstead o) Kust doing "hat ; "as told, ; sat do"n and studied "hat "as ,eing done 6hen #y ,oss asked "hy ; "asn5t coding, ; told hi# that ; "as thinking, a step ; did not consider optional ;t turns out that ; "as a,le to distill the 4B di))erent reports into Kust 4 report types %ll 4B reports could ,e generated using these three types and so#e para#eters %s a result the a#ount o) code needed to do the "ork "as cut do"n ,y at least a )actor o) 10 -e#e#,er the code that you never "rite is the =uickest to produces and the #ost ,ug )ree code you5ll ever #ake Hacking so#ething out o) e&istence is one o) the highest )or#s o) hacking Producing Lines of Code ; "as once tasked "ith updating a large "e, ,ased reporting syste# "ritten in Perl %t this ti#e #anage#ent decided to #easure lines o) code "ritten to see ho" productive its progra##ers "ere @ecause o) the /design3 o) the Perl synta&, the di))erence ,et"een ,ad progra##ers and good one is a#pli)ied !he )irst "eek, ; cleaned up the o,vious ine))iciencies and re#oved a lot o) redundant and useless code 8y score )or that "eek "as a,out +1,B00 lines produced So the progra# got s#aller even though ; added lots o) co##ents and a couple o) ne" )eatures 'or ne&t )e" "eeks ; continued to reduce the siFe o) the progra# !he ,ig change ca#e "hen ; took out the old style, /call )unction, check )or error, pass error up the call change3 logic and replaced it "ith e&ception ,ased error handling> !hat change lost us ?,000 lines 8y #anager asked #e "hy they should ,e paying #e the ,ig ,ucks since #y Dlines produced 1 "eek "as negative ; told the# that that "as precisely "hy they "ere paying #e the ,ig ,ucks @ecause it takes a really e&cellent progra##er to produce ne" )eatures in negative lines o) code
Page 11
Steve Oualline
The Problem: (ou pass a string 0char*2 into a )unction and the code gets con)used ,ecause so#eone accidentally #odi)ied the pointer The Hack: !ell the co#piler that the pointer is not to ,e changed !his hack #akes use o) one o) the #ore di))icult to understand concepts o) the C++ language, that o) const and pointers 6e5ll start "ith the declaration* const char* ptr_a;
Page 12
Steve Oualline
!he =uestion is /6hat does the const #odi)yS3 9oes it a))ect the pointer or does it a))ect the data pointed to ,y the pointerS ;n this case the const tells the co#piler that the character data is constant !he pointer itsel) can ,e reassigned const char* ptr_a; !hat #eans that "e can reassign the pointer* ptr_a = A New Value; @ut you can5t #odi)y the data pointed to ,y the pointer* *ptr_a = 'x'; // I !"A Go" let5s consider another declaration* char* const ptr_#; ;n this case the pointer is a))ected ,y the const !he data pointed to is not So "e can change the data ,eing pointed to* *ptr_# = 'x'; // egal !"A @ut "e can not change the pointer* ptr_# = A new string; // I %nd o) course there5s the o,vious declaration in "hich ,oth the pointer and the data are constant* const char* const ptr_c; Go" let5s go ,ack to our )unction call ;) "e are e&pecting constant data, then let5s speci)y it in the )unction para#eters* $oid displa%_string&const char* const the_string'; Go" any atte#pt to #odi)y the string "ill result in a co#pile ti#e error %nd co#pile ti#e errors are #uch easier to locate and )i& than run ti#e errors The const Memory Hack ;t5s not o,vious )ro# the synta& "here a const key"ord a))ects the pointer or the character @ut there is a si#ple #ne#onic trick that #ay help you re#e#,er "hich is "hich
Page 14
C++ Hackers Guide !he const #odi)ies the ele#ent it5s nearest 'or e&a#ple*
Steve Oualline
Page 1>
C++ Hackers Guide // 7e,ine how to draw the rectangle struct draw_para:s :%_draw_st%le; :%_rect=width = width; :%_rect=line_color = ./ /0_1 2!; :%_rect=,ill_color = ./ /0_3IN4; :%_rect=,ill = 6/ I7_5I ; :%_rect=stac8 = A1/V!_A ; :%_rect=la#el_,ont = 9+i:es9; :%_rect=la#el_si<e = (;; :%_rect=la#el = 96tart9; draw_rectangle&x() %() x*) %*) >:%_draw_st%le';
Steve Oualline
Go" instead o) passing para#eters ,y position they are passed ,y na#e !his #akes the code #ore relia,le 'or e&a#ple, you no longer have to re#e#,er i) the line color co#es )irst or the )ill color co#es )irst 6hen you "rite it as* :%_rect=line_color = ./ /0_1 2!; :%_rect=,ill_color = ./ /0_3IN4; it5s clear "hich is the line color and "hich is the )ill Hacking the Hack: !he draw_para:s structure can ,e used not only )or dra"ing a rectangle ,ut )or dra"ing other shapes as "ell 'or e&a#ple* draw_rectangle&x() %() x*) %*) >:%_rect'; draw_circle&x?) %?) radius) >:%_rect'; ;t is a good idea to #ake the de)ault value )or any para#eter Fero !hat "ay, you can set everything to the de)ault using the state#ent* :e:set&>:%_rect) '@;') si<eo,&:%_rect''; !he )rees you )ro# having to set values )or every ite# in the structure 'or e&a#ple, to dra" a red rectangle using the de)ault "idth, )ill, and la,el para#eters, use the )ollo"ing code* :e:set&>:%_rect) '@;') si<eo,&:%_rect''; :%_rect=line_color = ./ /0_0!7; draw_rectangle&x() %() x*) %*) >:%_rect'; ;) you are using C++, the draw_para:s structure can ,e #ade a class !he class can provide internal consistency checking to the user 0USetting the la,el to 5)oo5 "ith a point siFe o) 0 #akes no sense to #e U2
Page 1?
Steve Oualline
(ou need to de)ine constants to access the various ,its in the option ,yte 0@yte 22 One "ay o) doing this to de)ine a he&adeci#al constant )or each co#ponent // 1ad .ode const int /"_5 const int /"_5 const int /"_5 const int /"_5 A"_72 = ;xA;; A"_76 = ;xB;; A"_+67 = ;x*;; A"_!+. = ;x(;; // // // // 7isa#le update 7isa#le sa$e +arget sa$e disa#led !na#le thres= co:p=
!he pro,le# is that the relationship ,et"een 0&>0 and ,it A is not o,vious ;t5s easy to get the ,its con)used // "ood code const int /"_5 const int /"_5 const int /"_5 const int /"_5 A"_72 = ( CC D; A"_76 = ( CC E; A"_+67 = ( CC F; A"_!+. = ( CC B; // // // // 7isa#le update 7isa#le sa$e +arget sa$e disa#led !na#le thres= co:p=
Go" it5s easy to see that 0(CCB2 is ,it > Warning: 8ake sure you kno" "hich end is "hich ;n the previous e&a#ple ,it Fero is the least signi)icant ,it 0right#ost ,it2
Page 1A
Steve Oualline
@ut so#e people la,el ,it 0 as the #ost signi)icant ,it 0le)t#ost ,it2 'or e&a#ple the ;nternet Speci)ication -'C B71 de)ines the /!ype o) Service3 )ield as 0spelling errors in the original2*
Bits 0-2: Bit 3: Bits 4: Bits %: Bit (-): Precedence. 0 = Normal Delay, 1 = Low Delay. 0 = Normal T ro!" #!t, 1 = $i" T ro!" #!t. 0 = Normal &eli'ility, 1 = $i" &eli'ility. &eser*ed +or ,!t!re -se.
VSpelling errors in the original W 6e can still use our shi)t hack to de)ine ,its in this "ay Only "e start "ith the constant 0&80 and shi)t to the right 'or e&a#ple* // "ood code // 7ela% ,lag const unsigned int I3+/6_ /-7! AG = ;xA; HH ?; // +hroughput ,lag const unsigned int I3+/6_+I0/2"I32+ = ;xA; HH B; // 0elia#ilit% ,lag const unsigned int I3+/6_0! IA1I I+G = ;xA; HH F; 6arning* 8ake sure that you use unsigned int instead o) [signed] int "hen de)ining the constants Signed integers "ill cause the sign ,it to ,e replicated in the data yielding une&pected results Trivia: !he )ollo"ing is the de)initions as de)ined in the $inu& standard header )ile /usr/include/netinet/ip.h: Jde,ine I3+/6_ /-7! AG Jde,ine I3+/6_+I0/2"I32+ Jde,ine I3+/6_0! IA1I I+G ;x(; ;x;A ;x;B
(ou #ay have noticed that they don5t use this hack 6ithout looking at the previous page can you tell "hich ,it is represented ,y I3+/6_ /-7! AGS
Page 1B
Steve Oualline
Page 18
C++ Hackers Guide !his results in so#e strangeness in the header )iles* struct ti:esta:p K Ji, __1G+!_/07!0 == __ I++ !_!N7IAN unsigned int ,lags:B; unsigned int o$er,low:B; Jeli, __1G+!_/07!0 == __1I"_!N7IAN unsigned int o$er,low:B; unsigned int ,lags:B; Jelse J error 93lease ,ix C#its/endian=hH9 Jendi, L;
Steve Oualline
!here5s one other gotcha you have to ,e concerned a,out "ith ,it )ields !ake a look at the )ollo"ing code* struct ,lag_set K int #ig:(; int #igger:(; int #iggest:(; L; // === ,lag_set the_set; the_set=#ig = (; std::cout CC #ig ,lag is CC the_set=#ig CC std::endl; !he output o) this progra# is not /,ig )lag is 13 6hat is going onS !he pro,le# is that "e have a one ,it signed integer ;n a signed integer the )irst ,it is the sign ,it ;) the )irst ,it the nu#,er is negative So a single ,it signed nu#,er can only take t"o values, 0 and C1 So the state#ent* the_set=#ig = (; sets the sign ,it to 1 #aking the nu#,er negative, setting the )ield to C1
Steve Oualline
;deally the docu#entation should ,e e#,edded in the progra# as co##ents %)ter all, it5s di))icult to loose X a progra# )ile Ho"ever, all the nice "ord processor dra"ing )unctions you5re used to having "hen you "rite a docu#ent are #issing "hen you are "riting a progra# ;nstead you have to get creative "ith the #ono spaced single )ont used )or "riting progra#s Here5s one e&a#ple "hich uses %SC;; art to dra" lines )ro# the ,its to their description* /* * /"_6! !.+ para:eters #%te * * MNNNNNNNNNN 72 &7isa#le 2pdate' * OMNNNNNNNNN 76 &7isa#le 6a$e' * OOMNNNNNNNN +67 &+arget 6a$e 7isa#le' * OOOMNNNNNNN !+. &!na#le +hreshold .o:pression' * OOOOMMNNNNN +P. &+hreshold Pet .riteria' * OOOOOOMNNNN 0s$d &0eser$ed' * OOOOOOOMNNN 3 & ist 3ara:eter' * DEFB?*(; */
!he other #ethod is to use the that they use in the -'C docu#ents Here5s a co##ent #ade )ro# an e&cerpt )ro# -'C B71* /* * 1its ;N*: 3recedence= * 1it ?: ; = Nor:al 7ela%) ( = ow 7ela%= * 1its B: ; = Nor:al +hroughput) ( = Iigh +hroughput= * 1its F: ; = Nor:al 0eli#ilit%) ( = Iigh 0eli#ilit%= * 1it END: 0eser$ed ,or 5uture 2se= * * ; ( * ? B F E D * MNNNNNMNNNNNMNNNNNMNNNNNMNNNNNMNNNNNMNNNNNMNNNNNM * O O O O O O O * O 30!.!7!N.! O 7 O + O 0 O ; O ; O * O O O O O O O * MNNNNNMNNNNNMNNNNNMNNNNNMNNNNNMNNNNNMNNNNNMNNNNNM */ VSpelling errors in the original W
Page 20
Steve Oualline
Copying )ro# a standard like this has the added advantage o) )aith)ully reproducing the in)or#ation in the standard, thus producing good docu#entation %nd since all you did "as copy and past the a#ount o) "ork re=uired "as #inor !he only dra",ack to copy and paste is that any )la"s in the original, such as the spelling error a,ove are also reproduced
Steve Oualline
Go" in actual practice your call to the copy constructor #ay not ,e so o,vious 6hat "ill pro,a,ly happen is that you5ll accidentally call the copy constructor through para#eter passing or so#e other hidden code @ut the nice thing is that no" "hen you do call it, you5ll discover the pro,le# at co#pile and not run ti#e
Page 22
Steve Oualline
% lot o) people don5t understand "hat it #eans to declare a #e#,er varia,le static % instance o) a nor#al #e#,er varia,le is created "hen a ne" instance o) a class is created ;n other "ords a_$ar=:e:#er is a distinct and di))erent varia,le than #_$ar=:e:#er @ut static #e#,ers are di))erent 'or static #e#,er varia,le only one instance o) the varia,le is created period ;t is shared a#ong instances o) the class So in other "ords x_c:d=c:d_set is the sa#e as %_c:d=c:d_set (ou can also re)er to the varia,le "ithout an instance o) the class at all* c:d::c:d_set 06ell you could i) "e didn5t declare it private 2 Go" let5s take a look at our do_register )unction* $oid do_register&' K c:d_set=insert&this'; L !his si#ply insert a pointer to the current class into the list !he unregister )unction is Kust as si#ple* $oid unregister&' K c:d_set=erase&this'; L Go" co#es the )un one, the )unction "e call to e&ecute a co##and ;t is declared as a static #e#,er )unction so that "e #ay call it "ithout having a c:d varia,le around static $oid do_c:d&const char* const c:d_na:e' K @ecause it is static "e can call it "ith a state#ent like* c:d::do_c:d&cop%'; ote: static #e#,er )unctions can only access static #e#,er varia,les and glo,al varia,les !he ,ody o) the )unction is pretty straight )or"ard Yust loop through the set o) co##ands until you )ind one that #atches, then call the do_it #e#,er )unction static $oid do_c:d&const char* const c:d_na:e' K std::setCclass c:d*H::iterator cur_c:d; ,or &cur_c:d = c:d_set=#egin&'; cur_c:d R= c:d_set=end&'; MMcur_c:d' K Page 24 Copyright 2008, Steve Oualline
Steve Oualline
One o) the #ore interesting things a,out this syste# is "hat happens "hen you use class c:d to declare a glo,al varia,le ;n that case the co##and is registered ,e)ore #ain in called ;n other "ords C++ goes through the progra# looking )or glo,al varia,les and calling their constructors ,e)ore starting each progra# (ou have to ,e care)ul "hen doing this though !here is no guarantee concerning the order in "hich the classes are initialiFed @asically you don5t "ant to create any glo,al varia,les "ho5s constructor depends on a co##and ,eing registered !he co#plete class is listed ,elo"* Jinclude CsetH class c:d K pri$ate: static std::setCclass c:d*H c:d_set; const char* const na:e; pri$ate: $oid do_register&' K c:d_set=insert&this'; L $oid unregister&' K c:d_set=erase&this'; L $irtual $oid do_it&$oid' = ;; pu#lic: c:d&const char* const i_na:e':na:e&i_na:e' K do_register&'; L $irtual Qc:d&' K unregister&'; Page 2> Copyright 2008, Steve Oualline
Steve Oualline
pu#lic: static $oid do_c:d&const char* const c:d_na:e' K std::setCclass c:d*H::iterator cur_c:d; ,or &cur_c:d = c:d_set=#egin&'; cur_c:d R= c:d_set=end&'; MMcur_c:d' K i, &strc:p&&*cur_c:d'NHna:e) c:d_na:e' == ;' K &*cur_c:d'NHdo_it&'; return; L L throw&un8nown_c:d&c:d_na:e''; L L; % s#art hacker #ight note that "e could have used a std:::ap to hold our co##and list %)ter all a std:::ap takes a key and value pair and "ould eli#inate our lookup loop in do_c:d @ut the e&tra synta& needed to #ake a std::map "ork "ould get in the "ay o) the point o) this hack So "hile the class is not as e))icient code "ise, it is very e))icient ,ook "ise
Page 2?
Steve Oualline
class dictionar% K pri$ate: // ots o, stu,, that the user doesn't need to // worr% a#out= // &And this is the pro#le:' pu#lic: // === usual constructor / destructor stu,, $oid add_pair&const std::string> 8e%) const std::string> $alue'; const std::string> loo8up&const std::string> 8e%'; L; !he pro,le# is that this gives anyone "ho uses this class access to so#e o) the private i#ple#entation details o) the class The Hack: Hide the i#ple#entation details through the use o) an i#ple#entation class class dictionar% K pri$ate: dictionar%_i:ple:entation* i:ple:entation; pu#lic: Since "e don5t have to de)ine dictionar%_i:ple:entation in the header )ile this e))ectively hides the i#ple#entation and separates the inter)ace and the i#ple#entation Hacking the Hack: !here are several "ays o) i#ple#enting a dictionary 'or e&a#ple, i) "e are dealing "ith a,out 10C100 "ords, "e could i#ple#ent the dictionary using an array 'or 100C100,000 entries "e could use a dyna#ic list 'or over 100,000 the code can #ake use o) an e&ternal data,ase @ut "hat5s nice a,out de)ining a dictionary in this "ay is that the class can change the i#ple#entation on the )ly as conditions change 'or e&a#ple, the class can start "ith an array 6hen the nu#,er o) entries gro"s to #ore than 100 it can s"itch to a list ,ased i#ple#entation*
Page 2A
Steve Oualline
$oid dictionar%:: add_pair&const std::string> 8e%) const std::string> $alue' K i, &&i:ple:entationNHt%pe&' == A00AG_IP3 !P!N+A+I/N'>> &i:ple:entationNHsi<e&' H= PAS_A00AG'' K dictionar%_i:ple:entation* new_i:ple:entation = new dictionar%_as_list&i:ple:entation' delete i:ple:entation; i:ple:entation = new_i:ple:entation; L // === sa:e thing ,or list NH data#ase
i:ple:entationNHadd_pair&8e%) $alue'; !hus "e5ve not only hidden the dictionary i#ple#entation, ,ut "e5ve #ade it a,le to dyna#ically recon)igure itsel) depending on data load
The Problem: !here are lots o) "ays o) creating a linked list !here are only a )e" good ones The Hack: !he $inu& kernel5s linked list i#ple#entation 0See the )ile 1usr1include1linu&1list h in any kernel source tree 2 !here a large nu#,er o) things "e can learn )ro# this si#ple #odule 'irst since linked lists are a si#ple and co##on data structure it #akes sense to create a linked list #odule to handle the# %)ter all things can get con)used i) everyone i#ple#ents his o"n linked list :specially i) all the i#ple#entations are slightly di))erent Lesson !: Code -euse !he "ay the linked list is i#ple#ented is very e))icient and )le&i,le (ou can actually have ite#s that are put on #ultiple lists Lesson ": 'le&i,le design !he list )unctions are "ell docu#ented !he header )iles contains e&tensive co##ents using the 9o&ygen docu#entation convention 0See Hack A?2 Lesson #: Share your "ork 9ocu#ent it so others can use it
Page 2B
Steve Oualline
!here5s there5s a #echanis# in place to help persuade people to use this i#ple#entation and to avoid "riting their o"n ;) you su,#it a kernel patch containing a ne" linked list i#ple#entation you "ill ,e /politely3? told to use the standard i#ple#entation %lso your code "on5t get in the kernel until you do Lesson $: :n)orce#ent o) standard policy 8ostly through peer pressure So ,y looking at this i#ple#entation o) a si#ple linked list "e can learn so#ething 6hich leaves us "ith our )inal lesson* Lesson %: % good hacker learns ,y reading code "ritten ,y so#eone "ho kno"s #ore a,out this type o) progra##ing that you do
? !he ter# /polite3 has a di))erent #eaning "hen dealing "ith people "ho )re=uent the kernel #ailing lists
Page 28
Steve Oualline
A ;) you think that no progra##er "ould really progra# this "ay, Kust look at the design decisions #ade ,y a certain #aKor co##ercial operation syste# !hese people have to issue "eekly security patches to keep up "ith the sa)ety pro,le#s that they the#selves introduced ,ecause they decided to code and think in that order
Page 27
C++ Hackers Guide 'or e&a#ple, is the result o) the )ollo"ing code* i = ;; // 1ad code arra%TiMMU = i; !here are t"o su,Ce&pressions involving i !hese are* 1 i++ 2 i
Steve Oualline
!he co#piler is )ree to e&ecute the# in any order it "ants to So "hat co#piler you are using and even "hat co#pilation )lags are used can a))ect the result !here is no reason )or trying to keep everything on one line (ou co#puter has lots o) storage and a )e" e&tra lines "on5t hurt things % si#ple, "orking progra# is al"ays ,etter than a short, co#pact, and ,roken one So avoid side e))ects and put ++ and -- on lines ,y the#selves ;) "e re"rite the previous e&a#ple as* iMM; arra%TiU = i; !he order o) the operations is clear not only to the co#piler ,ut to anyone reading the code
Hack 13: Don6t '%t 7ssi*nment Statements Inside 7n! 8ther Statements
The Problem: ;t5s a classic #istake* using M instead o) MM Code like* i, &i = getch&'' K // 7o so:ething L The Hack: Gever include an assign#ent state#ent inside any other state#ent 0%ctually never include any state#ent inside any other state#ent, ,ut this one is so co##on it deserves its o"n hack 2 !he reason )or this is si#ple* (ou "ant to do t"o si#ple things right one at a ti#e 9oing t"o things at once in a co#ple&, and un"orka,le state#ent is not a good idea Page 40 Copyright 2008, Steve Oualline
Steve Oualline
!his hack )lies in the )ace o) so#e co##on design patterns 'or e&a#ple* // 7on't code li8e this while &&ch = getch&'' R= !/5' K putchar&ch'; L 'ollo"ing this sa)ety rule, our code looks like* // .ode li8e this while &true' K ch = getch&'; i, &ch == !/5' #rea8; putchar&ch'; L Go" a lot o) people "ill point out that the )irst version is a lot #ore co#pact So "hatS 9o you "ant co#pact code or sa)e codeS 9o you "ant co#pact code or understanda,le codeS 9o you "ant co#pact code or "orking codeS ;) "e take o)) the re=uire#ent that the code "orks, ; can #ake the code #uch #ore co#pact @ecause #ost people value things like code that is sa)e and "orking, it is a good idea to use #ultiple si#ple state#ents instead o) a single co#pact one !his hack is designed to keep things si#ple and constant %s a hacker "e kno" you are a clever progra##er @ut it takes a very clever progra##er to kno" "hen not to ,e clever
Steve Oualline
Luestion* 6hat5s WIDTHS ;) you ans"ered B you got it "rong !he preC processor is a very literal progra# !he value o) WIDTH is literally 8 1 @ut everyone kno"s that 8 Q 1 is B rightS Got everyone C++ does not :specially "hen used in a e&pression !he line* int points = -I7+I * D*; is translated ,y the preCprocessor into* int points = A N ( * D*; %s a result, the value o) points is not "hat the progra##er intended The Hack: .se const instead o) &define "henever possi,le ;) "e had de)ined "idth as* static const int -I7+I = A V (; // -idth o, page V :argin then our calculations "ould ,e correct !hat5s ,ecause "e are no" de)ining WIDTH using C++ synta&, not preCprocessor synta& .sing const has another ,ene)it ;) you #ake a #istake in the &define state#ent, the pro,le# #ay not sho" up until you actually use the constant !he C++ co#piler per)or#s synta& checking on const state#ents %ny synta& pro,le#s "ith these state#ents sho" up i##ediately and you don5t have to guess "here the pro,le# occurred
Hack 1+: I, :o% M%st Use 9de,ine '%t 'arenthesis 7ro%nd )he ;al%e
The Problem: !here are so#e ti#es that you Kust can5t use const Ho" do you avoid pro,le#s like the one sho"n in the previous hackS (ou #ight ask "hy can5t "e Kust use constS !he ans"er is that so#eti#es you need to create a header )ile that5s shared "ith a progra# in another language 'or e&a#ple the h2ph progra# that co#es "ith Perl understands &define, ,ut not const The Hack* %l"ays enclose &define values in 02 'or e&a#ple* Jde,ine -I7+I &A V (' // -idth o, page V :argin Go" "hen you use this in a state#ent like* Page 42 Copyright 2008, Steve Oualline
C++ Hackers Guide int points = -I7+I * D*; you get the correct value
Steve Oualline
Hack 1.: Use inline #%nctions Instead o, 'arameteri<ed Macros Whene1er 'ossi0le
The Problem: Para#eteriFed #acros can cause une&pected things to happen Consider the )ollo"ing case* Jde,ine 6W2A0!&x' &&x' * &x'' int i = F; int X = 6W2A0!&iMM'; 6hat5s the value o) jS !he ans"er is that it5s co#piler dependent %nd the value o) i is de)initely not A 6hyS Yust look at the code a)ter the #acro is e&panded* int X = &&iMM' * &iMM''; 'ro# this "e can see that i is incre#ent t"ice %lso since the order o) the operations is not speci)ied ,y the C++ standard, the actual value o) j is co#piler dependent Gote* 6e violated Hack 12 in this e&a#ple !his is another e&a#ple o) "hy that hack is i#portant The Hack: .se inline )unctions instead o) &define "henever possi,le $et5s see ho" our code "ould look "ith an inline )unction* static inline int sYuare&int x' K return &x * x'; L Go" "hen this )unction is called t"o things happen* j gets the correct value and i is incre#ented once ;n other "ords, the code ,ehaves Kust like it is "ritten %nd having so#ething look and act the sa#e "ay is a ,eauti)ul hack ote: So#eone ;5# sure is going to point out that the #acro "orks )or any type and the inline )unction only "orks )or integers !his pro,le# is easily solved ,y #aking the inline version a )unction template
Page 44
Steve Oualline
Hack 1/: I, :o% M%st Use 'arameteri<ed Macros '%t 'arenthesis 7ro%nd )he ar*%ments
The Problem: !he "ay the preCprocessor handles para#eteriFed #acros can so#eti#es lead to incorrect code 'or e&a#ple* // 7on't code li8e this Jde,ine 6W2A0!&x' &x * x' So "hat5s the value o) i in the )ollo"ing state#ent* int i = sYuare&( M *'; Should ,e 7 @ut the state#ent e&pands to* int i = &( M * * ( M *'; "hich gives us ? not 7 The Hack: Put parenthesis around every place you use a para#eter in a para#eteriFed #acro 'or e&a#ple* Jde,ine 6W2A0!&x' &&x' * &x'' Go" our e&panded assign#ent state#ent looks like* int i = &&( M *' * &( M *''; and "e5ll get the right ans"er ote: !his does not solve the incre#ent pro,le#s sho"n in Hack 1A !his hack should ,e only used i) you a,solutely #ust use para#eteriFed #acros and can5t use inline )unctions 0See also Hack 12 )or help avoiding the incre#ent pro,le# 2
Steve Oualline
4 ;) you don5t "rite code like this you don5t have to "orry a,out stupid =uestions The Hack: !he hacker5s ans"er is o,vious the third one Hackers kno" ho" to avoid trou,le ,e)ore it starts So i) "e never get near nasty code "e don5t have to "orry a,out ho" it "orks 0.nless "e have to deal "ith legacy code "ritten ,y nonChackers 2 %l"ays include OP "hen there5s any a#,iguity in your code !he previous e&a#ple should ,e "ritten as* i, &a' K i, &#' K do_so:ething&'; L else K do_so:ething_else&'; L L 'ro# this code it5s clear "hich if the else ,elongs to @eing o,vious is an i#portant part o) coding sa)ely !here5s enough con)usion and chaos in progra##ing already "ithout having so#eone add to it ,y e&ploiting o,scure ele#ents o) the C++ synta& % good hacker kno"s ho" to keep things si#ple, o,vious, and "orking
Page 4?
Steve Oualline
Consistency and si#plicity are key to sa)e progra##ing !he less you have to think and #ake decisions the less you can #ake the "rong decision % good hacker "ill produce a set o) rules and procedures so he can do things consistently and right %nother "ay o) saying this is a good hacker does a great deal o) thinking a,out things so he doesn5t have to do a great deal o) thinking !he si#pli)ied precedence rules are one e&a#ple o) this %l#ost no one re#e#,ers the o))icial 1B, ,ut re#e#,ering the si#pli)ied t"o is si#ple %pplying our hack it5s easy to )igure out the result o) the )ollo"ing e&pression* i = &( O ?' > &F CC *'; 0; kno" it5s not the sa#e result, ,ut this is "hat the progra##er intended in the )irst place 2
s=uare h
extern long int sYuare&int $alue';
s=uare cpp
int sYuare&int $alue' K return &$alue * $alue'; L ote: C++ is only partially type sa)e !he para#eters to a )unction are checked across #odules, the return values are not So "hat happens "hen this )unction is calledS !he sYuare )unction co#putes a nu#,er and returns the result, a 42 ,it integerB !he caller kno"s that the )unction returns a A> ,it integer Since 42 ,it return values and A> ,it return values are returned in di))erent registers, the calling progra# gets gar,age 6hat5s "orse the poor #aintenance progra##er is let "ondering ho" a )unction like sYuare "hich is to si#ple to )ail, is actually )ailing
Page 4A
Steve Oualline
The Hack: 8ake sure each #odule includes it5s o"n header )ile ;) the s=uare cpp )ile ,egan "ith* Jinclude sYuare=h the co#piler "ould notice the pro,le# and prevent you )ro# co#piling the code %nd pro)essional progra##ers kno" that it5s 10,000 ti#es easer to catch an o,vious pro,le# at co#pile ti#e than it is to locate a rando# value error in a running progra#
Page 4B
Steve Oualline
Page 48
C++ Hackers Guide 237A+! user_in,o 6!+ e:ail = ',redZwhate$er=co:' -I!0! user = '5'; 6! !.+ user) password 50/P user_in,o;
Steve Oualline
!he '(L(CT state#ent "ill return to the user all the user na#es and pass"ords in the data,ase )ood *+ 'ecurity Practices !he data,ase sche#a in this e&a#ple illustrates a poor data,ase design (ou never should sort sensitive in)or#ation 0pass"ord, social security nu#,er, credit card nu#,ers2 in any data,ase accessi,le directly )ro# the ;nternet Such in)or#ation should ,e kept in a dedicated secure co#puter "hich allo"s very li#ited access )ro# your o"n co#puters and no access )ro# any else ;t should ,e locked up tight %lso the data itsel) should ,e encrypted "ith a key that #ust ,e entered on the console o) the #achine at ,oot ti#e Only under e&tre#ely li#ited circu#stances should unencrypted data ,e trans#itted !he client 1 server connection should also ,e locked do"n as "ell !he client should never ,e a,le to ask the data,ase )or the pass"ord !he only thing it should ,e a,le to do is to ask /;s this pass"ord correctS3 %nd that =uestion should ,e trans#itted over an encrypted link )or added security $ooking up this data this "ay is not )oolproo), ,ut it does keep out #ost o) the ,ad guys %nd ,y the "ay storing sensitive data on a laptop or porta,le drive, especially credit card nu#,ers and social security nu#,ers is really, really stupid 9o not store sensitive in)or#ation on porta,le devices and don5t leave such devices in places like a hotel roo# "here they are easy to steal %lso any sensitive data on your laptop should ,e protected ,y a good encryption syste# !o prevent SL$ inKection attacks you should validate all the characters supplied ,y the user Here5s an e&a#ple o) ho" not to do it* Page 47 Copyright 2008, Steve Oualline
C++ Hackers Guide // 1ad code #ool $alidate_na:e&const char* const na:e' K ,or &int i = ;; na:eT;U R= '@;'; MMi' K i, &na:eTiU == '@''' return &,alse'; L return &true'; L
Steve Oualline
6hy is this code ,adS @ecause it only checks )or a ,ad character %ctually in SL$ there are #ore ,ad characters out there (ou shouldn5t check to #ake sure that the input does not contain ,ad character, you should #ake sure that everything is good // "ood code #ool $alidate_na:e&const char* const na:e' K ,or &int i = ;; na:eT;U R= '@;'; MMi' K i, &R isalnu:&na:eTiU'' return &,alse'; L return &true'; L ;t is #uch #ore secure to only good stu)) than to e&clude ,ad stu)) !hat5s ,ecause i) you #ake a #istake and #ake your /good stu))3 de)inition too restrictive you don5t cause a security hole in the progra# ;) you #ake a #istake in a /,ad stu))3 de)inition, ,ad things could get through -e#e#,er, Kust ,ecause you5re paranoid, it doesn5t #ean they aren5t out to get you
Page >0
Steve Oualline
@ut this code is also a security pro,le# % attacker can create a care)ully constructed string "hich over"rites the stack and let5s the ,ad guy e&ecute any code he "ants to !he gets )unction is so ,ad that the GG. gcc linker issues a "arning "henever it5s used
9tm#9cc:%;<%m.o4.te8t.08246: :n +!nction 3main7: : warnin": t e 3"ets7 +!nction is dan"ero!s and s o!ld not 'e !sed.
The Hack: .se ,gets instead // "ood code char lineT(;;U; ,gets&line) si<eo,&line') stdin'; !he ,gets call "ill not get #ore data than the varia,le can hold !his prevents attackers )ro# e&ecuting a stack s#ashing attack
Doing di ide !!!" goes into the ,u))er, then the progra# crashes "ith a
divide ,y Fero error, and the output is never displayed !his is "here the con)usion co#es )ro#
8 6hy an integer divide ,y Fero causes a )loating point e&ception is a =uestion that this ,ook does not deal "ith
Page >1
Steve Oualline
The Hack: 8ake sure that "hen de,ugging that the ,u))er is )lushed a)ter every output !here are several "ays o) doing this !he )irst is to e&plicitly )lush every state#ent* std::cout CC 7oing di$ide === CC std::,lush; !his "orks, ,ut you have to re#e#,er to do the )lush )or every state#ent !he other "ay is to set the unit#uf )lag "hich tells C++ to )lush a)ter every output operation !his only has to ,e done once at the top o) your progra# std::cout CC std::unit#u,; // 5ro: now on e$er%thing is auto:aticall% ,lushed ;n C the sa#e thing can ,e acco#plished ,y setting the _I$%&' )lag using the set #uf )unction* static char #u,TF(*U; // 1u,,er ,or standard out set$#u,&stdout) #u,) _I/N1V) si<eo,&#u,''; @eing a"are o) "hat5s going inside the progra# is very use)ul to a hacker So#eti#es the co#piler, li,rary or the #achine "ill do strange things to you @ut kno"ing the internals is only hal) the ,attle <no"ing ho" to get around the internal li#itations o) the syste# is the #ark o) a good hacker
Page >2
Steve Oualline
int dataT(;U; // === int i = ((; assert&&i H= ;' >> &i C (;''; // "ood exa:ple // 0otten i:ple:entation dataTiU = F; !his "orks ,ut there is a pro,le# "ith 6e5ve used the constant 10 in t"o places 0!he declaration and the assert 2 ;t "ould ,e easy )or so#eone to change one and not the other One solution to this is to use na#ed constants // 1etter code Jinclude CcassertH const int 7A+A_6I[! = (;; int dataT7A+A_6I[!U; // === int i = ((; assert&&i H= ;' >> &i C 7A+A_6I[!''; // 1etter) // #ut not #est dataTiU = F; ;deally "e don5t "ant to have to use even na#ed constants i) "e can help it ;t is possi,le to create a ,ounds checking assert using the data varia,le alone* assert&&i H= ;' >> &i C si<eo,&data' / si<eo,&dataT;U'''; So "hat is going on hereS !he e&pression si<eo,&data' returns the nu#,er o) ,ytes in the array data @ut "e need the nu#,er o) ele#ents in the varia,le, not the nu#,er o) ,ytes !he solution is to divide the nu#,er o) ,ytes in the array ,y the nu#,er o) ,ytes in the )irst ele#ent !he result is an e&pression "hich gives us the nu#,er o) ele#ents si<eo,&data' / si<eo,&dataT;U' Go" ,eing true hackers, "e don5t "ant to have to "rite the sa#e e&pression over and over again, so let5s create a #acro to #ake our li)e easier /* * assert_#ounds&$ar) index' V Pa8e sure an index is in * #ounds= * * -arning: +his onl% wor8s is $ar is a arra% $aria#le and * not a pointer= Page >4 Copyright 2008, Steve Oualline
C++ Hackers Guide */ Jde,ine assert_#ounds&$ar) index' @ assert&&index H= ;' >> &index C &si<eo,&$ar' / si<eo,&$arT;U'''';
Steve Oualline
@ecause "e5re such nice progra##ers "e5ve docu#ented our #acro and even included a "arning descri,ing its li#itations %rray over)lo"s are one o) the #ost co##on progra##ing errors and are e&tre#ely )rustrating to try and locate !his code doesn5t eli#inate the#, ,ut it does cause ,uggy code to a,ort early in a "ay that #akes the pro,le# tre#endously easier to )ind Warning: !he assert state#ent is not guaranteed to a,ort your progra# 'or e&a#ple, consider the state#ent* assert&,alse'; !his state#ent /o,viously3 "ill cause the progra# to a,ort ,ecause the assert is al"ays )alse ;) the progra# is co#piled "ith N7!12" de)ined, all the asserts are co#piled out ;n other "ords, i) N7!12" is de)ined the previous state#ent does nothing , -eal 'ystem Crash (ou should only use assert in progra#s "here a,orting is an accepta,le ,ehavior ;n #ost cases "hen a progra# crashes it is an annoyance )or the user ,ut not a disaster !hat is not al"ays the case ;n 177A so#e people started running a progra# on an upgraded hard"are plat)or# %s a result o) the hard"are upgrade the progra# ran longer than e&pected and one o) the counters over)lo"ed Since this "as %9% code, it triggered an e&ception !he e&ception "as not caught so the syste# e&ecuted the de)ault e&ception handler and halted the processor !his "as not a good thing to do !he hard"are plat)or# that had ,een upgraded "as the %riane > rocket to the %riane ? rocket !he co#puter in =uestion "as tasked "ith keeping the rocket pointed into the air
Page >>
Steve Oualline
!echnically the rocket didn5t crash !he launch director ,le" it up "hen it started to head )or the ground !he cost o) that ,ug "as esti#ated to ,e a,out R?00,000,000 0.S2
C++ Hackers Guide arra%_t%pe> operatorTU&int index' K assert&index H= ;'; assert&index C A00AG_6I[!'; return &>dataTindexU'; L
Steve Oualline
%nother )eature o) this te#plate is that it doesn5t provide a "ay o) converting an array into a pointer ;t is up to you "hether or not you consider this a )eature or a ,ug
Page >A
Steve Oualline
6+A+!_A 3IA case to )all through or did he #ake a #istakeS ;n other "ords is that )act that 6+A+!_A 3IA calls do_alpha and do_#eta intentional or an
errorS // 0otten code switch &state' K case 6+A+!_A 3IA: do_alpha&'; case 6+A+!_1!+A: do_#eta&'; #rea8; // ==== 'ro# this code it5s i#possi,le to tell "hat the progra##er intended The Hack: @e o,vious a,out "hat you do ;) you intend )or one case to )all through to another indicate it "ith a co##ent like // 5all +hrough // 7ecent code switch &state' K case 6+A+!_A 3IA: do_alpha&'; // 5all through case 6+A+!_1!+A: do_#eta&'; #rea8; // ==== %)ter all ,eing a hacker #eans that you have to ,e clever, not that you have to ,e sneaky
Steve Oualline
!he code string == ; co#pares the address o) the string against 0 !hey should not ,e Fero and the assert )ails Since a )ailing assert prints the condition that )ailed, no" "hen your progra# dies, you "ill get a nice error #essage telling you "hat happens @ut i) the progra# dies "hen the assert state#ent )ails, "hy put in the a,ortS ,ecause it5s possi,le to use co#pile ti#e s"itched 0N7N7!12"2 to co#pile out the assert state#ents So "hat this code really says, is die "ith a nice error #essage %nd i) you5re still alive, Kust die
Page >8
Steve Oualline
S"itches i) so#ething can have only have a li#ited nu#,er o) values, you should al"ays add a default clause to catch things that )all out o) range* switch &$owel' K case 'e': MMe_count; #rea8; case 'i': MMi_count; #rea8; case 'a': case 'o': case 'u': // Ignore these $alues #rea8; de,ault: assert&IN+!0NA !00/0: Vowel not legal == ;'; a#ort&'; L One thing to notice a,out this code, "e clearly indicate "hat vo"els are to ,e ignored ,y the state#ent* // Ignore these $alues %)ter all, the idea is to not only ,e sa)e ,ut to ,e clear and o,vious as "ell
Hack 31: Create 8pa$%e )!pes AHandlesB Which can 0e Checked at Compile )ime
The Problem: (ou are creating an %P; "hich uses a lot o) handles 'or e&a#ple, )ont handles, graphics handles, "indo" handles, color handles, and so )orth One solution is to create a /di))erent3 type )or each handle* // 7angerous code t%pede, short int t%pede, short int t%pede, short int t%pede, short int ,ont_handle; graphic_handle window_handle; color_handle;
!he )ollo"ing code sho"s these types in operation* ,ont_handle the_,ont = ,ind_,ont&+i:es) (;) 1old'; color_handle the_color = ,ind_color& ight 0ed'; draw_text&the_,ont) the_color'; Page >7 Copyright 2008, Steve Oualline
Steve Oualline
@ut there is a pro,le# "ith doing things this "ay @oth ,ont_handle and color_handle have the sa#e ,asic type So the co#piler "ill not co#plain i) you do the )ollo"ing* // 3ara:eters #ac8wards draw_text&the_color) the_,ont'; ;deally "e "ould like a solution "here the co#piler "ill co#plaint i) "e #i& the handles !he other re=uire#ent "e have is that the handle take up as little space as possi,le, pre)era,le t"o ,ytes The Hack* .se a s#all structure to hold the handles $et5s take a look at the )ollo"ing handle declarations* // 6a,e code t%pede, struct K short int handle; L ,ont_handle; t%pede, struct K short int handle; L graphic_handle t%pede, struct K short int handle; L window_handle; t%pede, struct K short int handle; L color_handle; So "e5ve replaced a t"o ,yte integer "ith a t"o ,yte structure 6hat5s the ,ig dealS !he ,ig deal is type checking Go" the handles have a di))erent structure and no co##on ,ase type %s a result, the co#piler "ill do type checking ;n other "ords the )ollo"ing is legal* draw_text&the_,ont) the_color'; and the )ollo"ing is not* draw_text&the_color) the_,ont'; // Incorrect and illegal Gote all the advantages o) the handle syste# are still in places Handles are still s#all opa=ue entities, ,ut no" they are type checked as "ell !hus "e "e have a hack that gets around C++5s "eek types and turns the# into stronger ones Page ?0 Copyright 2008, Steve Oualline // .orrect and legal
Steve Oualline
si<eo,&' operator "ill return the correct siFe and the :e:set call "ill do the
right thing
Page ?1
Steve Oualline
So#e progra##ers consider the )ollo"ing good progra##ing practice* //Not a good idea struct data_struct K int i() i*; L; data_struct* data_ptr; data_ptr = new data_struct; //==== //1ad code :e:set&data_ptr) '@;') si<eo,&data_struct''; % pro,le# can occur i) you #odi)y the code to and #odi)y "hat data_ptr is pointing to // +his code contains a :ista8e struct data_struct K int i() i*; L; struct data_struct_i:pro$ed K int i() i*; int extra_data; L; data_struct_i:pro$ed* data_ptr; data_ptr = new data_struct_i:pro$ed; //==== // Pista8e :e:set&data_ptr) '@;') si<eo,&data_struct''; ;n the real "orld, there5s going to ,e a lot o) code ,et"een the declaration o) data_ptr and the line clearing it* :e:set&data_ptr) '@;') si<eo,&data_struct''; So the progra##er can ,e )orgiven i) he didn5t see this line "hen he changed the type o) the varia,le data_ptr @ut and error has still ,een introduced and this is not good The Hack: .se si<eo,&*ptr' to deter#ine the siFe o) dyna#ic data Go #atter ho" you change the type o) data_ptr, the e&pression si<eo,&*data_ptr' "ill al"ays contain the right nu#,er o) ,ytes So this code al"ays "orks* Page ?2 Copyright 2008, Steve Oualline
Steve Oualline
Page ?4
Steve Oualline
6e "ant the result to al"ays ,e null ter#inated, so "e e&plicitly handle the e&ception case and #ake sure that our string is null ter#inated %gain, "e use the si<eo,&' operator to #ake sure "e get the right siFe na:eTsi<eo,&na:e'N(U = '@;'; Putting this all together "e get the code* // "ood code char na:eT(;U; strncp%&na:e) si<eo,&na:e') 96te$e /ualline9'; na:eTsi<eo,&na:e'N(U = '@;'; Warning: !he si<eo,&na:e' only "orks i) na#e is declared as an array ;) it is declared as a pointer, then si<eo,&na:e_ptr' returns the siFe o) the pointer, not the data that it is pointing to
Page ?>
Steve Oualline
ote: ;t is possi,le to avoid all C style string related #e#ory pro,le#s ,y using C++ std:::string strings @ut a lot o) code still uses the old style strings and there are per)or#ance issues "ith C++ strings ote: % ne" )unction called strlcp% has ,een introduced in so#e C1C++ li,raries "hich allo"s )or sa)e string copies Ho"ever, it5s not standard, it5s not in all li,raries, and Solaris and Open@S9 have i#ple#ented it di))erently @ut i) you have it, ,y all #eans use it
Steve Oualline
Putting it all together "e get this sa)e version o) the progra#* // "ood code char na:eT(;U; strncp%&na:e) 9/ualline9) si<eo,&na:e''; na:eTsi<eo,&na:e'N(U = '@;'; // .oncatenation exa:ple strncat&na:e) 9) 9) si<eo,&na:e' V strlen&na:e' N('; na:eTsi<eo,&na:e'N(U = '@;'; // +his is reYuired strncat&na:e) 9/ualline) si<eo,&na:e' V strlen&na:e' N('; na:eTsi<eo,&na:e'N(U = '@;'; ote: % ne" )unction called strlcat has ,een introduced in so#e C1C++ li,raries "hich allo"s )or sa)e string catenation Ho"ever, it5s not standard, it5s not in all li,raries, and Solaris and Open@S9 have i#ple#ented it di))erently @ut i) you have it, ,y all #eans use it
Page ?A
Steve Oualline
Steve Oualline
One classic e&a#ple o) an ar,itrary li#itation "as the A>0< li#itation % =uote attri,uted to @ill Gates7 states /A>0< ought to ,e enough #e#ory )or anyone 3 @ut it "as only a short "hile a)ter the original PC ca#e out that people started inventing addCon cards "ith special drivers designed to get around the A>0< li#itation %nother e&a#ple is the ls co##and !he initial version used single characters )or options 0-l, -,, etc 2 9o a #an ls no" and you5ll )ind that al#ost all the single letters 0upper and lo"er case2 are ,eing used ,y this co##and 'i)ty t"o 02AH22 options "ere Kust not enough @y li#iting options to a single character the designers o) ls li#ited their e&panda,ility So#eone had to devise a ne" option synta& 0--long-options2 to get around this pro,le# The 'enior Citi/en Truant One state5s citiFen tracking syste# li#ited a person5s age to t"o digits So "hen one o) its citiFens reached 100 her age "as reset to 0 !his "asn5t too ,ig a pro,le# !he real trou,le ca#e "hen she reached 10B and the state sent a truant o))icer out to her house to )ind out "hy her parents had not enrolled her in the )irst grade
Page ?8
C++ Hackers Guide pri$ate: unsigned int si<e; char* data; pu#lic: a_class&unsigned int i_si<e' K si<e = i_si<e; data = new charTsi<eU'; L // Iere's the pro#le: code a_class operator = &const> a_class other' K deleteTU data; data = N2 ; si<e = other=si<e; data = new charTsi<eU; :e:cp%&data) other=data) si<e'; L L
Steve Oualline
Go" consider "hat happens "hen a varia,le is assigned to itsel) !he )irst step* (= 7elete :% data deletes the data )or the destination varia,le 0*this2 Ho"ever, the destination varia,le is also the source varia,le 0other_one2, the data )or this is deleted as "ell ;n )act the only copy o) the data is deleted !he progra# "ill )ail "hen "e get to the step* *= Allocate a new structure the sa:e si<e as other_one's data ,ecause there is no data in other_one, "e deleted it in step 1 The Hack: Progra# de)ensively and check )or sel) assign#ent e&plicitly :very nonCtrivial class should have the )ollo"ing at the ,eginning o) each assign#ent operator )unction* a_class> opeator = &const a_class> other_one' K i, &this == >other_one' return &*this'; // 6el, assign:ent detected // ==== !his little ,it o) insurance can prevent a really nasty pro,le# )ro# occurring
Page ?7
Steve Oualline
Page A0
Steve Oualline
So "hat "e are actually doing is reducing a di))icult to solve pro,le# 0rando# over"rites o) #e#ory cause rando# results2 to one that5s easier to solve 0as soon as the #e#ory goes ,ad, the progra# crashes2 !his type o) code helped #e locate a rather unusual pro,le# "ith so#e C code "hat had ,een upgraded to C++ ;n this case the )irst call to chec8_sentinels crashed the progra# %nalyFing the progra# ; discovered that the pro,le# "as caused so#e"here ,et"een "hen the constructor "as called and the )irst sentential veri)ication call So ; put a ,reakpoint in the constructor and "as planning to single step through the code until ; )ound the pro,le# !he progra# crashed ,e)ore the constructor "as called So ; "as le)t "ith a puFFle /Ho" can a progra# call a #e#,er )unction ,e)ore it calls the constructorS3 !he ans"er "as surprisingly si#ple !he class "as ,eing created "ith
:alloc ; told you it "as once C !urns out that it "as not =uite )ully ported )ro# C to C++ -eplacing :alloc "ith new solved the pro,le# Hack (1: Sol1e Memor! 'ro0lems "ith 1al*rind
The Problems: @ad pointers, "riting o) the end o) allocated #e#ory, #e#ory leaks C++ gives you lots o) )le&i,ility "hen it co#es to #e#ory #anage#ent (ou are allo"ed to allocate and deallocate #e#ory and directly #anipulate pointers 'le&i,ility co#es "ith a cost @ecause the language allo"s you to allocate #e#ory, you can scre" up the allocations Si#ilarly you can scre" up the deallocation and use o) pointers Since there are no ,uiltCin sa)ety checks in C++ "hat do you do to protect your codeS The Hack* .se valgrind !he valgrind progra# runs your progra# in a sort o) virtual #achine 8e#ory accesses undergo e&tra checking !hat #akes it possi,le to detect certain types o) pointer errors !hese include* 1 .sing )reed #e#ory 2 6riting past the end o) a allocated ,lock
Page A1
C++ Hackers Guide 4 6riting past the ,eginning o) an allocated ,lock > 8e#ory $eaks $et5s take a look at a s#all e&a#ple* ( * ? B F E D A ] (; (( Jinclude Ciostrea:H int :ain&' K int* ptr = new intT(;U; int* ptr_# = new intT(;U; *&ptrM((' = F; ptr_# = N2 ; exit&;'; L
Steve Oualline
ote: (ou #ay have noticed that "e violated our o"n sa)ety rules ,y not putting asse(t state#ents ,e)ore each pointer access @ut the purpose o) this code is to cause pro,le#s, not catch the#, so "e disa,led the sa)ety5s 6hat are the pro,le#s "ith this codeS On line 8 "e access ele#ent 11 o) a 10 ele#ent array On line 7 "e Fero out the only pointer to the #e#ory "e allocated in line A thus causing a #e#ory leak $et5s look at "hat valgrind does "hen this progra# is run
? *al"rind --lea@-c ec@=+!ll .9'ad2mem ==31)%%== Aemc ec@, a memory error detector. ==31)%%== 1o#yri" t 416 2002-200(, and BN- BPL7d, 'y <!lian Ceward et al. ==31)%%== -sin" Li'D0E re* 1(%F, a li'rary +or dynamic 'inary translation. ==31)%%== 1o#yri" t 416 2004-200(, and BN- BPL7d, 'y G#en;or@s LLP. ==31)%%== -sin" *al"rind-3.2.1, a dynamic 'inary instr!mentation +ramewor@. ==31)%%== 1o#yri" t 416 2000-200(, and BN- BPL7d, 'y <!lian Ceward et al. ==31)%%== ,or more details, rer!n wit : -* ==31)%%== ==31)%%== :n*alid write o+ siHe 4 ==31)%%== at 08F04F)12: main 4'ad2mem.c##:F6 ==31)%%== Iddress 0842%30%4 is 4 'ytes a+ter a 'loc@ o+ siHe 40 alloc7d ==31)%%== at 08401JD%%: o#erator new=>4!nsi"ned6 4*"2re#lace2malloc.c:1J%6 ==31)%%== 'y 08F04F(,%: main 4'ad2mem.c##:%6 ==31)%%== ==31)%%== 0&&G& C-AAI&K: 1 errors +rom 1 conte8ts 4s!##ressed: 21 +rom 16 ==31)%%== malloc9+ree: in !se at e8it: F0 'ytes in 2 'loc@s. ==31)%%== malloc9+ree: 2 allocs, 0 +rees, F0 'ytes allocated. ==31)%%== ,or co!nts o+ detected errors, rer!n wit : -* ==31)%%== searc in" +or #ointers to 2 not-+reed 'loc@s. ==31)%%== c ec@ed 104,)J( 'ytes. ==31)%%==
Page A2
Steve Oualline
40 'ytes in 1 'loc@s are de+initely lost in loss record 1 o+ 2 at 08401JD%%: o#erator new=>4!nsi"ned6 4*"2re#lace2malloc.c:1J%6 'y 08F04F)0%: main 4'ad2mem.c##:(6 L0IL C-AAI&K: de+initely lost: 40 'ytes in 1 'loc@s. #ossi'ly lost: 0 'ytes in 0 'loc@s. still reac a'le: 40 'ytes in 1 'loc@s. s!##ressed: 0 'ytes in 0 'loc@s. &eac a'le 'loc@s 4t ose to w ic a #ointer was +o!nd6 are not s own. To see t em, rer!n wit : --s ow-reac a'le=yes
%)ter so#e chatter, the progra# catches the )irst thing the tool notices is the "rite to an illegal #e#ory location*
==31)%%== :n*alid write o+ siHe 4 ==31)%%== at 08F04F)12: main 4'ad2mem.c##:F6 ==31)%%== Iddress 0842%30%4 is 4 'ytes a+ter a 'loc@ o+ siHe 40 alloc7d ==31)%%== at 08401JD%%: o#erator new=>4!nsi"ned6 4*"2re#lace2malloc.c:1J%6 ==31)%%== 'y 08F04F(,%: main 4'ad2mem.c##:%6
%)ter the progra# )inishes, valgrind checks the heap to see i) any #e#ory "as lost ;n this case it )ind that "e allocated so#e #e#ory at line A and lost it
==31)%%== 40 'ytes in 1 'loc@s are de+initely lost in loss record 1 o+ 2 ==31)%%== at 08401JD%%: o#erator new=>4!nsi"ned6 4*"2re#lace2malloc.c:1J%6 ==31)%%== 'y 08F04F)0%: main 4'ad2mem.c##:(6
!he tool is s#art ;t didn5t report the #e#ory "e allocated on line ? as lost even through "e allocated it and never )reed it !hat5s ,ecause at the ti#e the progra# e&ited there "as a pointer to this ,lock o) #e#ory ;n other "ords so#eone "as using it at e&it ti#e, so it "as not lost !he valgrind tool is not per)ect can not )ind pro,le#s "ith local or glo,al arrays, only allocated #e#ory @ut still it does a very good Ko, o) )inding a large nu#,er o) di))icult to locate pro,le#s
Page A4
C++ Hackers Guide Consider the )ollo"ing e&a#ple* ( * ? B F E D A ] (; (( (* Jinclude Ciostrea:H static $oid print_state&' K int state;
Steve Oualline
i, &state' K std::cout CC 96tate alpha9 CC std::endl; L else K std::cout CC 96tate #eta9 CC std::endl; L L
%t line B "e use the value o) state to decide i) "e do the alpha or ,eta parts !here5s Kust one pro,le#, "e never ,other to give state a value So "hich state "ill ,e e&ecutedS !hat depends on "hat the previous )unction le)t on the stack ;n other "ords, state "ill ,e set to so#e rando# nu#,er Ho" do you detect such thingsS ;t5s di))icult using the de,ugger ;) you print the value o) state and get 481204>7, ho" do you kno" i) that is correct or incorrectS The Hack: valgrind to the rescue !he valgrind progra# also checks to see i) you use any uninitialiFed data ;t5s actually rather clever a,out this ;) you assign one uninitialiFed varia,le to another, it "on5t co#plain 0!his actually happens a lot "hen doing :e:cp% and other si#ilar operations 2 @ut i) you try to use uninitialiFed data to #ake a decision 0inside an if state#ent )or e&a#ple2 it "ill co#plain loudly 'or e&a#ple "hen "e run the previous progra# under valgrind "e get*
... c atter ... ==2(4FF== 1onditional M!m# or mo*e de#ends on !ninitialised *al!e4s6 ==2(4FF== at 08F04F)DI: #rint2state46 4!init.c##:)6 ==2(4FF== 'y 08F04FF41: main 4!init.c##:1(6 Ctate al# a ... more c atter ...
!his clearly sho"s us that line B has a pro,le# "ith uninitialiFed data
Page A>
Steve Oualline
Page A?
Steve Oualline
Go" "e need a )unction "hich returns a pointer to this array* t%pede, #ase_arra%* #ig_,un&int $alue'; 'inally "e declare a pointer to this ite#* #ig_,un* the_pointer; Go" you #ay have noticed that "e used )our typedef state#ents to de)ine this one pointer 6e could have done this in one state#ent @ut the goal o) this hack "as to de)ine the pointer "ith a #ini#u# o) e))ort, not a #ini#u# o) code Clarity is one =uality highly valued ,y good hackers and ,y ,reaking do"n this pro,le# into #ultiple, s#all typedef state#ent "e can use #any s#all clear state#ents in place o) one large co#ple& and i#possi,le to understand C++ declaration !he )ull code 0including co##ents2 )ollo"s* // +%pe de,inition ,or a ,unction which ta8es // a character argu:ent and returns an integer t%pede, int #ase_,unction&const char* const arg'; // 3ointer to a #ase ,unction t%pede, #ase_,unction* #ase_,unction_ptr; // An arra% o, pointers to our #ase ,unction t%pede, #ase_,unction_ptr #ase_arra%TU; // 5unction which returns an arra% o, ,unction // pointers t%pede, #ase_arra%* #ig_,un&int $alue'; // 5inall% a pointer to the thing we wished // to point to #ig_,un* the_pointer; %s hackers "e are e&pected to think out o) the ,o& and look ,eyond the initial pro,le# One =uestion that "e haven5t dealt "ith is /6hy "ould you ever need such a pointerS3 ;n the real "orld, a good hacker "ould not design a ,etter "ay to declare the pointer, he "ould design code so that a pointer like this "as never needed in the )irst place :li#ination o) needless co#ple&ity is one o) the attri,utes o) a truly great hacker
Page AA
Steve Oualline
Hack (+: Create )e&t #iles Instead o, -inar! 8nes Whene1er #easi0le
The Problem: (ou need save the con)iguration data 0or other data2 )ro# your progra# 9o you use a ,inary )ile or and te&t )ileS The Hack: .se te&t ;t al#ost al"ays #ake things easier .G;T is an e&cellent e&a#ple o) hacker design One o) the key design )eatures that #ake the syste# "ork as "ell as it does is that al#ost all the con)iguration )iles are te&t !here are nu#erous advantages to te&t )iles !he )irst is that they are hu#an reada,le 6hen your progra# "rite a te&t )ile, the contents o) the )ile can ,e e&a#ined ,y si#pling looking at it (ou don5t have to create so#e )ancy data du#per to look at the )ile !his illustrates one o) the #aKor advantages o) te&t )iles* transparency (ou can see "hat5s going on in a te&t )ile %lso you change change it easily using an editor !his #eans that i) you progra# needs a con)iguration )ile and that )ile is in te&t )or#at, then a te&t editor can ,e used to edit the con)iguration 0; didn5t say it "ould ,e easy or pretty, ,ut it can ,e done 2
Page AB
Steve Oualline
%lso i) the con)iguration in)or#ation te&t ,ased, other people can easily "rite tools "hich edit the con)iguration )ile On $inu& you5ll )ind literally hundreds o) progra#s "hich con)igure net"ork settings !hat5s ,ecause the net"ork con)iguration is stored in a te&t )ile and easily accessi,le to everyone %gain, one o) your goals as a hacker is to #ake things a si#ple and easy to play "ith as possi,le !e&t )iles let you do this @inary )iles are only use)ul "hen you are processing huge a#ount o) data 0video, graphics, data,ases, etc 2 6hen you are dealing "ith 100,000,000 records or #ore, then the overhead associated "ith te&t )iles can #ake your progra# slo" do"n tre#endously ;n that case ,inary )iles are ,etter @ut )or si#ple things like con)iguration )iles, settings )iles, and ,asic data te&t )iles are ,est Per)or#ance is not an issue 6ho cares i) it takes 0 004 seconds to start your progra# instead o) 0 001 @ut people do care a,out clarity, correctness, and interopera,ility and that "here te&t )iles are ,est Ho. ot to *esign a Configuration 'ystem
!he conse=uences o) a ,ad design are "orth study too $et5s look at one very co##on syste# )or storing con)iguration settings 'irst o) all, all the con)iguration in)or#ation )or every progra# on the entire syste# is stored in one location !here are several pro,le#s "ith this* 1 % single "ild progra# can accidentally totally destroy all the settings 0!he solution to this pro,le#* 9on5t redesign, the con)iguration syste#, provide a ela,orate ,ackup syste# so "hen destruction does occur you can recover Q sort o) 2 2 8ake the )ile ,inary so no one can easily read it e&cept "ith an %P; that you supply 4 <eep the )or#at secret and only the user edit the con)iguration data using the tool you provide @y keeping things secret you a,solutely prevent anyone )ro# "riting a ,etter progra# > @ecause all settings are stored in one location, you5ve #ade it i#possi,le to create several con)iguration )iles to ,e used )or di))erent situations (ou li#it everyone on the #achine to one con)iguration period Page A8 Copyright 2008, Steve Oualline
Steve Oualline
? 'inally ,ecause con)iguration data can only ,e stored on the local #achine in a single location, con)iguration sharing is i#possi,le !he syste# ;5ve ,een descri,ing is the 8icroso)t 6indo"s -egistry ;t is )ascinating )ro# a design point o) vie" ,ecause it gives good designers so#e #any opportunities to ask /6hat "ere they thinking "hen they did thisS3
Page A7
Steve Oualline
!here are #any di))erent "ays o) doing this !he #ethod ; pre)er is to think up a "ord that descri,es the progra# ;5# creating 'or e&a#ple /H%C<S3 !aking the )irst > letters and seeing "hat the %SC;; nu#,ers )or the# ; get* H % C < >8 >1 >4 >@
Putting these together gives us the nu#,er ;xBAB(B?B1 !he pro,le# "ith this nu#,er is that ,ecause it is )our %SC;; characters and the )ile can easily ,e con)used "ith a te&t )ile So "e add ;xA;A;A;A; to the nu#,er giving us a ;x.A.(.?.1 !he result is our #agic nu#,er* // +he :agic nu:#er at the #eginning o, each hac8 ,ile const long unsigned int IA.4_PA"I. = ;x.A.(.?.1 ; !he )inal step is to "rite out a )ile "ith our ne" #agic nu#,er in it and see i) the $inu& )ile co##and can identi)y it as an e&isting nu#,er 0ML 1iles !he T8$ )ile )or#at has ,een designed to solve a great #any o) the pro,le#s "ith )ile )or#ats ;t5s structured so that you can design =uite co#ple& things, it hu#an reada,le 0sort o)2, and you can easily validate it
Page B0
Steve Oualline
// +he :agic nu:#er at the #eginning o, each hac8 ,ile const long unsigned int IA.4_PA"I. = ;x.A.(.?.1 ; // +he :agic nu:#er on a :achine with a di,,erent #%te // order const long unsigned int IA.4_PA"I._6-I+.I = ;x.1.?.(.A ; // ===== long unsigned int :agic; in_,ile=read&>:agic) si<eo,&:agic''; i, &:agic == IA.4_PA"I.' K process_,ile&'; L else i, &:agic == IA.4_PA"I._6-I+.I' K process_,ile_a,ter_,lipping_#%tes&'; L else K throw&,ile_t%pe_exception& 5ile is not a hac8 data ,ile ''; L !he idea is si#ple, )irst check to see i) "e have a nor#al )ile and process it i, &:agic == IA.4_PA"I.' K process_,ile&'; 6e notice that a nor#al #agic nu#,er is ;x.A.(.?.1 On a #achine "ith a di))erent ,yte order the #agic nu#,er is ;x.1.?.(.A ;) "e detect a #agic nu#,er that #atches this value, "e kno" "e have a ,yte )lipped )ile and process it* const long unsigned int IA.4_PA"I._6-I+.I = ;x.1.?.(.A ; // ==== L else i, &:agic == IA.4_PA"I._6-I+.I' K process_,ile_a,ter_,lipping_#%tes&'; ote* %lthough this syste# "orks, you do have to #aintain t"o version o) the )ile reading progra# !his can ,e a signi)icant #aintaina,le and risk pro,le# (ou #ay "ant to consider using the ne&t hack instead
Steve Oualline
;n order to #ake data trans#ission plat)or# independent a standard ,yte order called /Get"ork @yte Order3 "as created % nu#,er o) )unctions "ere added to the C li,rary to convert ite#s to and )ro# net"ork ,yte order !he include*
1unction
a a a a
Meaning long in host )or#at to net"ork )or#at short in host )or#at to net"ork )or#at long in net"ork )or#at to host )or#at long in net"ork )or#at to host )or#at
$et5s see ho" this #ight ,e used "hen "riting a )ile* // +he :agic nu:#er at the #eginning o, each hac8 ,ile const long unsigned int IA.4_PA"I. = ;x.A.(.?.1 ; short int ite:_count = (F; // Nu:#er o, ite:s in the ,ile short int ,ield_length = ((; // ength o, next ,ield // === long unsigned int :agic = htonl&IA.4_PA"I.'; out_,ile=write&>:agic) si<eo,&:agic''; short int write_ite:_count = htons&ite:_count'; out_,ile=write&>write_ite:_count) si<eo,&write_ite:_count''; short int write_,ield_length = htons&,ield_length'; out_,ile=write&>write_,ield_length) si<eo,&write_,ield_length''; Si#ilar code is used on the read side to #ake things porta,le
C++ Hackers Guide 2 -ecord length 0> ,yte integer2 4 -ecord data 0length Q 8 ,ytes o) data2
Steve Oualline
!his is a deceptively si#ple )or#at %lthough si#ple, it leaves lots o) roo# )or e&pansion $et5s start "ith the code used to read the records ;t #ust read the )irst 8 ,ytes, get the length, then read the rest o) the data !he entire record is then returned to the reader )or processor Eery si#ple % good hack %ll the progra# has to do is to look a the record type to deter#ine "hat type o) data is in the record !hen it can process the record Go" "hat happens "hen "e need to e&pand and enhance our data strea# %ll "e have to do is to add a ne" record type !he reader doesn5t have to ,e changed ;t can still process the record ,ecause it doesn5t have to kno" the type %ll "e have to do is add a ne" record handler to the #ain progra# 'or e&a#ple* struct record K int t%pe; // 0ecord t%pe int length; // ength o, record uintA dataT;U; // 7ata &$aria#le length'; L; // ==== switch &record_$ar=t%pe' K case 0!._6+A0+: do_start&record_$ar'; #rea8; case 0!._6+/3: do_stop&record_$ar'; #rea8; case 0!._3A26!: do_pause&record_$ar'; #rea8; de,ault: std::cout CC -A0NIN": 2n8nown record t%pe CC record_$ar=t%pe CC Ignored CC std::endl; #rea8; L 6ith code like this it5s easy to add a handler )or a ne" record Ge" handlers easily )it into the sche#a Page B4 Copyright 2008, Steve Oualline
Steve Oualline
%lso this code "ill "ork )or ,oth past and )uture version o) the )ile ;t "orks "ith )uture versions ,ecause it skips records it does not kno" a,out So i) "e add a ne" record type such as ,-._/0I1, the progra# "ill still run ;t "on5t process records it doesn5t kno" a,out, ,ut it "on5t crash either !his ,uiltCin resilience is the hall#ark o) a really good hack
Page B>
Steve Oualline
!his hack has proved use)ul to #ysel) in a nu#,er o) occasions !he )irst "as a )ile syste# pro,le# ;t see#ed that "hen the co#puter "as shutdo"n and there "ere )iles ,eing "ritten to the disk, the operating syste# "ould pad the un"ritten sectors "ith ,locks containing all Feros 'ortunately the #agic nu#,ers "ere there and the progra# realiFed that it had read so#ething that "as hal) a good record and hal) so#ething else and discarded the data !he other pro,le# caught ,y this syste# "as a really nasty data corruption ,ug !he pro,le# "as eventually traced to code in an entirely di))erent #odule "hich sent out :C8ail alerts "hen an error condition occurred Here5s the code $et5s see i) you can spot the pro,le#* pid_t child_pid = ,or8&'; i, &child_pid == ;' K // -e are the child s%ste:&send_e:ail_alert'; exit&;'; L ;) you didn5t spot the ,ug ; can understand ;t took #e a,out a "eek o) testing to pinpoint this code and locate the pro,le# !he pro,le# is very hard to see %)ter all this entire #odule shares no code "ith the record "riting #odule ;n particular the output )ile handle does not e&ist at all outside the record "riter %lso the code in =uestion does no ;1O ;t doesn5t even #anipulate #e#ory so it couldn5t ,e #e#ory corruption So "hat is going onS !here are t"o parts to this pro,le# !he )irst is the call* pid_t child_pid = ,or8&'; !his creates a duplicate o) the #ain process %ll )ile handles are no" shared ,et"een the t"o processes So "here ,e)ore there "as one process "ith the output )ile open, no" there are t"o !he ,or8 call also duplicates the #e#ory o) the parent process !his includes all the ;1O ,u))ers )or all the )iles !his includes the output )ile Ge&t "e co#e to the line* exit&;'; %ll this does is e&it the progra#, rightS Got e&actly $et5s take a look at the docu#entation )or this )unction* Page B? Copyright 2008, Steve Oualline
Steve Oualline
+he exit&' ,unction causes nor:al progra: ter:ination and the the $alue o, status > ;?DD is returned to the parent &see wait&*''= All ,unctions registered with atexit&' and on_exit&' are called in the re$erse order o, their registration) and all open streams are flushed and closed= 5iles created #% t:p,ile&' are re:o$ed=
!he e2it )unction actually does =uite a lot ;n particular it )lushes the "rite ,u))ers )or any )iles open )or "riting Since "e inherited a set o) open )iles and their ,u))ers )ro# the parent, they "ill ,e )lushed !hus this call "rites so#e data to the )ile !he #ain progra# "ill also "rite so#e data to the )ile "hen it5s ,u))ers get )ull Since these t"o "rites are not coordinated the data is corrupted !his "as a nasty pro,le# to )ind @ut the )act that the code "as "ritten "ith record protection in it, catching the pro,le# "as #uch easier :arly on it "as o,vious that turning on alerts cause the progra# to co#plain a,out record corruption !he only hard part "as looking at the code and trying to )igure out the pro,le# 6hat #ade this nasty is that the logs "ere getting corrupted, ,ut only i) alerts "ere turned on @ut these #odules had nothing in co##on !he shared no )unctions, logic, or #e#ory ;t took =uite so#e ti#e to )ind out that the pro,le# "as that they did share so#ething* ;1O ,u))ers, ,ut that sharing "as very "ell hidden
Hack +2:
The Problem: (ou are )orking o)) a process and do so#e "ork and then e&it, "ithout doing anything to the ;1O ,u))ers in the process (ou can5t use the e2it )unction ,ecause o) the pro,le#s descri,ed in Hack ?1 The Hack: .se _e2it !he _e2it )unction stops your progra# !hat5s all it does, stop the progra# ;t does not pass go, it does not collect R200 @ut #ore i#portantly it does not )lush any ;1O ,u))ers %ll that happens "hen you call _e2it is that your process goes a"ay
Page BA
Steve Oualline
!his is very use)ul "hen you5ve )orked o) a process that has done it5s "ork and needs to stop -e#e#,er e2it )lushes things and can cause all sorts o) trou,le "ith shared )iles !he _e2it call avoids this pro,le#
Page BB
Steve Oualline
Hack +3: Mark temporar! de0%**in* messa*es "ith a special set o, charactersE
The Problem: 9e,ugging ,y adding print state#ents is still a very po"er)ul de,ugging techni=ue @ut ho" do you identi)y print state#ents designed to output in)or#ation )or a speci)ic pro,le# vs the print state#ents that should ,e there The Hack* @egin all te#porary de,ugging output "ith the characters /DD3 'or e&a#ple* i = ,ind_index&'; std::cout CC JJ ,ind_index returned CC i CC std::endl; !he /DD3 serves several purposes 'irst, it identi)ies the state#ent as a te#porary de,ug state#ent Ge&t "hen you do )ind the pro,le# it5s easy to re#ove the# %ll you have to do is go through and )ind each line containing a /DD3 and delete it
Page B8
Steve Oualline
6ell on #ost syste#s there5s a tool designed )or the searching and #anipulation o) large te&t )iles ;t5s called your syste# editor $et5s see ho" this "orks in action 'irst let5s suppose you5ve done an e&haustive test o) your syste# and logged the results Out o) ?,000 tests, three )ail "ith an error Si#ple start up your editor and search )or the string /:--O-3 (ou5ll locate the line o) the )irst error 6ant to see "hat happened Kust ,e)ore the error, scroll up and take a look !he editor not only lets you look at the data ,ut annotate it as "ell (ou can add co##ents and annotations to the log as you )igure out "hat is going on %nd unlike paper notes, edits in the )ile can ,e inserted into an :C8ail in case you have to use the ;nternet )or help $og )iles are a great source o) in)or#ation and the te&t editor is a great "ay to e&ploit this in)or#ation 0See Hack 12B )or in)or#ation on ho" to Ei# to e&a#ine log )iles 2
Steve Oualline
Ge&t "e create a loop to process the co##and line argu#ents ;n this e&a#ple "e5re are using the GG. getopt )unction to scan the argu#ents 6e use the argu#ent speci)ication $:: to indicate the only option is N$ and that it can ,e )ollo"ed ,y options para#eters 0!his is indicated ,y the /**3 a)ter the /v3 2 while &(' K int opt = getopt&argc) arg$) 9$::9'; Go" "e process the options !here are t"o possi,le "ays o) speci)ying Cv !he )irst is Kust Cv alone ;n that case "e turn on all de,ugging in)or#ation "ith the line* :e:set&$er#ose_letters) N() si<eo,&$er#ose_letters''; @ut i) the options has argu#ents then "e only set the letters o) the given options* ,or &unsigned int i = ;; optargTiU R= '@;'; MMi' $er#ose_lettersT static_castCintH&optargTiU'U = true; Putting it all together "e get the )ollo"ing code )or parsing the ver,ose option* switch &opt' K case '$': i, &optarg == ;' K :e:set&$er#ose_letters) N() si<eo,&$er#ose_letters''; L else K ,or &unsigned int i = ;; optargTiU R= '@;'; MMi' $er#ose_lettersTstatic_castCintH&optargTiU'U = true; L #rea8; // === process other options Checking to see need to issue a de,ugging #essage is si#ple 'or e&a#ple to check )or :alloc logging "e use the code* i, &$er#ose_lettersT':'U' K std::cerr CC 7oing a :alloc o, CC si<e CC #%tes; L ptr = :alloc&si<e'; Page 80 Copyright 2008, Steve Oualline
Steve Oualline
;n actual practice "e "ould de)ine a constant )or ':', ,ut )or this short e&a#ple "e5ll e&cuse the ,ad progra##ing practice !his "ay o) speci)ying "hat to log allo"s us to use all the lo"er case letters, all the upper case letters, and all the digits to select "hat to log %nd i) that5s not enough there are lost o) punctuation characters "e can use as "ell 0%nd i) that5s not enough, your progra# is pro,a,ly too ,ig to ever ,e de,ugged any"ay 2 !"o attri,utes #ake this a good hack 'irst it is si#ple Second it is e&tre#ely )le&i,le ;n other "ords it a si#ple solution to a co#ple& pro,le#, and si#ple solutions are al"ays good
Steve Oualline
@ut so#eti#es you need to instru#ent the #ain loop o) a progra# that #ysteriously hangs a)ter )our days o) operations Since you don5t have a couple o) tera,ytes o) )ree disk space )or the log )iles, you need to turn on de,ugging a)ter the progra# hangs in order to )ind out "hat is going on that is #aking things nuts !hat5s "here this hack is #ost use)ul
Go" all you have to do to turn on de,ugging is to create the )ile 1t#p1prog de,ug on !o turn it o)) si#ply re#ove the )ile !his hack should ,e only used "hen you a,solutely need to turn de,ugging on and o)) "hile the progra# is running and you can use signals 0Hack ?A2 !he access syste# call is e&pensive and "ill slo" your progra# do"n i) used )re=uently So although this hack is use)ul, ,e a"are o) its li#itations
(pon )rror
The Problem: (our progra# has detected an internal pro,le# that needs de,ugging @ut the progra# is not ,eing de,ugged Ho" do you let the progra##er at the pro,le#S The Hack: 9e)ine a )unction "hich starts the de,ugger on a running progra# ote: !he )ollo"ing code is $inu& speci)ic ;) you are running on a .G;T like syste# it should ,e easy to port it to that syste# ;) you are running 8icroso)t 6indo"s, you5re on your o"n
Page 82
Steve Oualline
!he ,asic idea o) the progra# is that "hen a de#ug_:e )unction call occurs that the progra# should start the de,ug 0gd,2 and attach it to the running process Sounds si#ple, ,ut there are a )e" details to "ork out 'irst let5s see "hat "e need to tell gd, start the de,ugging process !he initial gd, co##ands are* 1 attach Cpid> de,ugged Q %ttach the de,ugger to the progra# ,eing
2 echo 7e#ugger gd# started@n V $et the user kno" "hat has happened 4 s%:#ol /proc/Cpid>/exe Q !ell gd, "here to )ind the sy#,ol ta,le )or the process > #rea8 gd#_stop Q Stop at a nice stopping point ? shell touch Cflag-file> Q !ell the progra# that gd, is attached 08ore on this later2 A continue Q Continue e&ecution and stop at the correct location !he )irst gd, co##and* attach Cpid> attaches the de,ugger to the progra# 0<pid> is replaced ,y the process id o) the progra# to ,e de,ugged 2 !he de,ugger is no" in control o) the progra# %ctually i) "e "ere in a #ini#alist )ra#e o) #ind, "e "ould stop here @ut the de,ug session is in a sorry state !he sy#,ol ta,le has not ,een loaded and don5t kno" i) "e stopped in the correct thread or at a kno" location So "e e&ecute a )e" #ore co##ands to #ake things a little nicer !he ne&t co##and* echo 7e#ugger gd# started@n outputs a greeting #essage !hat "ay the user that "e5ve started the de,ugging process Ge&t "e load the sy#,ol ta,le 'or that "e need the na#e o) the progra# )ile One "ay o) )inding this is to talk look at the progra# na#e and do a P%!H search )or the e&ecuta,le )ile @ut $inu& is nice to provide a sy#,olic link )ro# /proc/CpidH/exe to the e&ecuta,le, so "e Kust e&ploit this )eature to load our sy#,ol ta,le Page 84 Copyright 2008, Steve Oualline
Steve Oualline
Go" "e tell gd, to stop at a good place ;n )act "e5ve de)ined a good place to stop called gd#_stop, so "e5ll set a ,reakpoint there #rea8 gd#_stop 6hen the de,ugger is attached to a progra#, the progra# stops !he pro,le# is "e don5t kno" "here the progra# is stopped ;t could ,e 80 levels deep into so#e )unction called ,y de#ug_:e 6hat "orse, "e could ,e dealing "ith a threaded progra# ;n that case "e #any not even ,e stopped in the thread that caused the error !he solution to this pro,le# is to set a stop in a kno" location 0gd#_stop2 and tell the de,ugger to continue 6hen "e stop at gd#_stop "e kno" "here "e are and "e are sure to ,e in the correct thread %)ter de#ug_:e starts gd, it "aits around )or the de,ugger to start !his is done using the loop* ]E: ]D: ]A: ]]: while &access&,lag_,ile) 5_/4' R= ;' K sleep &('; L
!his loop "aits around )or a )lag )ile to ,e created %s soon as it sho"s, the progra# kno"s that the de,ugger is running and it can continue ;n order to create the )lag )ile, "e issue the )ollo"ing co##and to gd,* touch C,lag_,ileH 'inally "e tell gd, to continue %t this point the e&ecution o) the progra# continues )or a short "hile until the progra# reaches gd#_stop !he code to do all this "ork is listed in the )ull de,ugJ#e c #odule at the end o) this hack 8ostly it5s a #atter string processing to get the co##ands into the co##and )ile Go" let5s talk a,out the actual invocation o) the gd, co##and ;deally "e should ,e a,le to Kust use a syste# call to e&ecute the co##and* gd# NNco::and=<command-file> ;n this e&a#ple <command-file> "ill ,e replace ,y a te#porary )ile containing the co##ands "e listed a,ove @ut it5s not as si#ple as that ;t never is
Page 8>
Steve Oualline
6hat is our progra# is a dae#on running in ,ackground ;t has no standard in and standard out ;) "e started gd, there "ould ,e no ter#inal in "hich to type co##ands % solution to this pro,le# is to start our o"n ter#inal "indo" !his done "ith the co##and* xter: N#g red Ne gd# Vco::and=<command-file> !his starts a ne" &ter# progra# in "hich our de,ugger "ill run 6e set the ,ackground to red using the options N#g red -ed is used ,ecause it gets our attention @esides the red screen o) death sounds ,etter than the ,lue screen o) death 'inally "e tell &ter# to e&ecute the gd, co##and through the use o) the Ne option Go" that "e5ve done all this let5s see ho" this )unction #ight ,e used in a progra# Here5s so#e code that handles a varia,le that it either ,lack or "hite 0at least under nor#al, sane circu#stances2* Jinclude de#ug_:e=h // ==== switch &#lac8_or_white' K case 1 A.4: do_#lac8&'; #rea8; case -II+!: do_white&'; #rea8; de,ault: std::cerr CC IN+!0NA std::endl; de#ug_:e&'; #rea8; L
;n this case the varia,le #lac8_or_white undergoes a sanity test ;) things are insane "e start the de,ugger ote: !his only "orks )or progra#s "hich are used internally ;) you are giving a progra# to a custo#er "ithout source code, this syste# is not that use)ul
!he )ull source code )or the de,ugJ#e c )ile )ollo"s Page 8? Copyright 2008, Steve Oualline
C++ Hackers Guide (: *: ?: B: F: E: D: A: ]: (;: ((: (*: (?: (B: (F: (E: (D: (A: (]: *;: *(: **: *?: *B: *F: *E: *D: *A: *]: ?;: ?(: ?*: ??: ?B: ?F: ?E: ?D: ?A: ?]: B;: B(: B*: B?: BB: BF: Page 8A
Steve Oualline
/************************************************ * de#ug_:e NN A :odule to start the de#ugger * * ,ro: a running progra:= * * * * -arning: +his code is inux speci,ic= * ************************************************/ Jinclude Cstdio=hH Jinclude Cunistd=hH Jinclude Cs%s/para:=hH Jinclude Cstdli#=hH Jinclude 9de#ug_:e=h9 static int in_gd# = ;; // +rue i, gd# started
/************************************************ * gd#_stop NN A place to stop the de#ugger * * * * Note: +his is not static so that the * * de#ugger can easil% ,ind it= * ************************************************/ $oid gd#_stop&$oid' K print,&9"d# stop@n9';,,lush&stdout'; L /************************************************ * start_de#ugger NN Actuall% start * * the de#ugger * ************************************************/ static $oid start_de#ugger&$oid' K int pid = getpid&'; // /ur 3I7 // +he na:e o, the gd# ,ile char gd#_,ile_na:eTPAS3A+I !NU; // 5ile that's used as a ,lag // to signal that gd# is running char ,lag_,ileTPAS3A+I !NU; // +he ,ile with the gd# in,or:ation in it 5I ! *gd#_,ile; // .o::and to start xter: Copyright 2008, Steve Oualline
C++ Hackers Guide BE: BD: BA: B]: F;: F(: F*: F?: FB: FF: FE: FD: FA: F]: E;: E(: E*: E?: EB: EF: EE: ED: EA: E]: D;: D(: D*: D?: DB: DF: DE: DD: DA: D]: A;: A(: A*: A?: AB: AF: AE: AD: AA: A]: ];: Page 8B char c:dTPAS3A+I !NM(;;U; i, &in_gd#' return; /* 3re$ent dou#le de#ugs */
Steve Oualline
/* * .reate a co::and ,ile that contains * attach CpidH J Attaches to the process * echo ==== J !chos a welco:e :essage * s%:#ol /proc/CpidH/exe * J oads the s%:#ol ta#le * #rea8 gd#_stop J 6et a #rea8point in * shell touch /t:p/gd#=,lag=CpidH * J .reate a ,ile that tells us * J that the de#ugger is running * continue J .ontinue the progra: */ sprint,&gd#_,ile_na:e) 9/t:p/gd#=\d9) pid'; gd#_,ile = ,open&gd#_,ile_na:e) 9w9'; i, &gd#_,ile == N2 ' K ,print,&stderr) 9!00/0: 2na#le to open \s@n9) gd#_,ile_na:e'; a#ort&'; L sprint,&,lag_,ile) 9/t:p/gd#=,lag=\d9) pid'; ,print,&gd#_,ile) 9attach \d@n9) pid'; ,print,&gd#_,ile) 9echo 9 9@7e#ugger gd# started@@n@9@n9'; ,print,&gd#_,ile) 9s%:#ol /proc/\d/exe@n9) pid'; ,print,&gd#_,ile) 9#rea8 gd#_stop@n9'; ,print,&gd#_,ile) 9shell touch \s@n9) ,lag_,ile'; ,print,&gd#_,ile) 9continue@n9'; ,close&gd#_,ile'; /* 6tart a xter: window with the * de#ugger in it */ sprint,&c:d) 9xter: N,g red 9 9Ne gd# NNco::and=\s >9) Copyright 2008, Steve Oualline
C++ Hackers Guide ](: ]*: ]?: ]B: ]F: ]E: ]D: ]A: ]]: (;;: (;(: (;*: (;?: (;B: (;F: (;E: (;D: (;A: (;]: ((;: (((: gd#_,ile_na:e'; s%ste:&c:d'; /* Now sleep until the de#ugger starts and * creates the ,lag ,ile */ while &access&,lag_,ile) 5_/4' R= ;' K sleep &('; L in_gd# = (; gd#_stop&'; L
Steve Oualline
/************************************************ * de#ug_:e NN 6tart the de#ugger * ************************************************/ $oid de#ug_:e&$oid' K start_de#ugger&'; gd#_stop&'; L
Page 88
Steve Oualline
&static_castC$oidH &__#uiltin_expect &RR&9-e are ,ailing9 R= ;') (' _ ; : &__assert_,ail &9@9-e are ,ailing@9 R= ;9) 9assert=cpp9) ?) __30!++G_52N.+I/N__') ;'''; 'ro# this "e can see that the )unction __assert_,ail is called "hen an assertion is triggered :arlier in the output the co#piler is even nice enough to provide us "ith a prototype* extern . K extern $oid __assert_,ail & __const char *__assertion) __const char *__,ile) unsigned int __line) __const char *__,unction' throw &' __attri#ute__ &&__noreturn__''; L Go" all "e have to do is supply our o"n version o) __assert_,ail "hich calls de#ug_:e /******************************************************** * __assert_,ail NN .alled when an assert ,ails= * * 6tarts the de#ugger= * * * * Note: gcc speci,ic= 7i,,erent co:pilers use * * di,,erent internal routines to handle #ad * * asserts= * ********************************************************/ $oid __assert_,ail& const char *const what) const char *const ,ile) const int line) const char *const ,unct ' K print,&9Assert ,ailed: \s@n9) what'; print,&95AI 20! at: \s:\d@n9) ,ile) line'; print,&95unction is \s@n9) ,unct'; de#ug_:e&'; a#ort&'; L One thing to notice a,out this )unction is that it calls a#ort a)ter de#ug_:e= !hat5s to prevent a careless progra##er )ro# typing continue in a de,ugging session and atte#pting to continue a o,viously )ailed progra# Page 87 Copyright 2008, Steve Oualline
Steve Oualline
!he de#ug_:e )unction "as originally "ritten to de,ug a #o,ile phone si#ulation progra# !he progra# had ,een a,andon )or a long ti#e ,ecause it "as e&tre#ely ,uggy 6hen ; got it the progra# "as e&tre#ely ,uggy and e&tre#ely out o) date !he progra# #ade e&tensive use o) threads and )re=uently a thread "ould crash 'inding out "hich thread had cause the pro,le# "as e&tre#ely di))icult as the gd, thread related co##ands didn5t "ork too "ell on this syste# So ; invented de#ug_:e to help solve this pro,le# One interesting aspect o) this progra# "as its unusual )ailure #odes Luite )re=uently a thread "ould trigger an assertion )ailure and start the de,ugger 6hile the de,ugger "as staring, another thread "ould )ail and atte#pt to start the de,ugger %ny progra##er can "rite code that causes an assertion to )ail and a,ort the progra# ;t takes a real hacker to get #ultiple assertions to )ail in a single run
C++ Hackers Guide ,or &i = ;; i C F;;;; MMi' K Ji,nde, WWW i, &i == BAD' de#ug_stop&'; Jendi, /* WWW */ // 3ro#le: code ,ollows
Steve Oualline
Go" all "e have to do is to start our de,ugger and put a ,reakpoint in
de#ug_stop -ight ,e)ore the pro,le# occurs this procedure "ill ,e called
thro"ing us into the de,ugger 6e can then single step through the progra# until "e )ind the error !here are a couple o) things to note a,out this code 'irst de,ugJstop is a glo,al )unction !he reason )or this is that so#e de,uggers have a hard ti#e )inding static )unctions !he reason "e use Ji,de, WWW )or our de,ugging code is descri,ed in Hack B2 @asically it5s an easy to "ay to identi)y te#porary code
Page 71
Steve Oualline
!here are other "ays o) indicating a #aKor section ,reak 'or e&a#ple you can #ake a heading that spans the entire line* /* Page 72 Copyright 2008, Steve Oualline
Steve Oualline
* CCCCCCCCCCCCCCCCC I// 6ection 5ollows HHHHHHHHHHHHHHHHH */ %nd )inally "e have a really i#portant section header* /******************************************************** ********************** -A0NIN" ************************* ********************** -A0NIN" ************************* ********************** -A0NIN" ************************* ********************************************************/ /* * 7o not atte:pt to dri$e hea$% eYuip:ent while reading * this #oo8= */
'or
10 %ctually so#e very sophisticated %SC;; art can ,e produced Yust not ,y progra##ers
Page 74
C++ Hackers Guide /* * * * * * * * */ MNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNM O Na:e: ____________________ O O Address: ____________________ O O .it%: ____________________ O MNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNM OCN NAP!_6I[! NHO O OCNNN 1 AN4_6I[! NNNNHO
Steve Oualline
;n this e&a#ple "e5ve not only created a )igure ,ut at the sa#e ti#e docu#ented the constants "e used )or the di#ension constants NAP!_6I[! and
1 AN4_6I[!
11 !he )irst ; told this Koke to a colleague he laughed )or a,out three #inutes then handed #e his copy o) Hitachi 'ortran Eolu#e ;; 0Eolu#e ; "as at the translator5s 2
Page 7>
Steve Oualline
+he ICsol$e_itH progra: sol$es all the worlds pro#le:= `ust input the pro#le: on the co::and line and the solution will #e output= =head( /3+I/N6 +he ICsol$e_itH ta8es the ,ollowing options: =o$er B =ite: 1CNuH 6ol$e the pro#le: ,or the uni$erse) not Xust the world= =#ac8 =head( IPI+A+I/N6
.urrentl% totall% uni:ple:ented= =head( A2+I/0 6te$e /ualline) !CltHouallineZwww=oualline=co:!CgtH= =head( ./3G0I"I+ .op%right *;;D 6te$e /ualline= +his progra: is distri#uted under the "3 = =cut */ Go" you can run your source code through one o) the PO9 converters such as pod2te&t and get a )or#atted version o) your docu#entation*
NIA0
CKNGPC:C
Page 7?
Steve Oualline
D0C1&:PT:GN T e Nsol*e2itN #ro"ram sol*es all t e worlds #ro'lem. <!st in#!t t e #ro'lem on t e command line and t e sol!tion will 'e o!t#!t. GPT:GNC T e Nsol*e2itN ta@es t e +ollowin" o#tions: -! Col*e t e #ro'lem +or t e !ni*erse, not M!st t e world.
L:A:TIT:GNC 1!rrently totally !nim#lemented. I-T$G& Cte*e G!alline, Oo!allinePwww.o!alline.comQ. 1GPK&:B$T 1o#yri" t 200) Cte*e G!alline. T is #ro"ram is distri'!ted !nder t e BPL.
Page 7A
Steve Oualline
!his tool allo"s you to use specially )or#atted co##ents to inCline docu#entation inside your code Here5s a short e&a#ple* /** * @#rie, +he #asic report speci,ication * * +his class co:pletel% descri#es all the para:eters * needed to produce a report */ class 0eport6pec K /** Na:e o, the report */ pu#lic: const char* const na:e; /** * Add a new report para:eter * * @para: na:e Na:e o, the para:eter * @para: $alue Value o, the para:eter */ $oid add_para:& const char* const na:e) const char* const $alue '; L; 6hen run through 9o&ygen this produces set o) H!8$ docu#entation pages "hich can ,e vie"ed in any ,ro"ser*
Page 7B
Steve Oualline
Page 78
Steve Oualline
!his syste# does provide an e&cellent syste# )or docu#enting your progra#s i) you5re "illing to )ollo" the conventions and "rite the co##ents correctly On the other hand i) you5re dealing "ith a lot o) code that didn5t do this, check out the ne&t hack
Hack ..: Use the Lin%& Cross Re,erence to =a1i*ate Lar*e Codin* 'roFects
The Problem: (ou5re dealing "ith a poorly designed ?,000,000 line proKect and you5re getting lost The Hack* .se the $inu& Cross -e)erence to generate a cross re)erenced version o) your code !he $inu& Cross -e)erence 0l&r212 is a progra# "hich produces a hyperCte&t ,ased #arkup o) your code (ou can get a copy )ro# http*11l&r linu& no1 ;t has a nu#,er o) nice )eatures such as the a,ility to locate any identi)ier in the code and sho" every place that it is used 'igure 2 sho"s the syste# ,eing used to ,ro"se a )ile
12 9on5t let the na#e )ool you ;t "ill cross re)erence things other than $inu&
Page 77
Steve Oualline
Page 100
Steve Oualline
Page 101
Steve Oualline
Page 102
Steve Oualline
C++ Hackers Guide Jde,ine 7&x' Jx const char* const state_na:e = K 6+A+!_ I6+ L; Junde, 7
Steve Oualline
6e can no" output the na#e o) a state using a state#ent like* std::cout CC 9+he good state is 9 CC state_na:eT6+A+!_"//7U CC std::endl; Limitations: !his only "orks )or enu: lists "here the things are in nu#erical order ;) you assign values to ite#s this "ill not "ork 'or e&a#ple* enu: error_code K1A7=BB) V!0G_1A7=FF) +!00I1 ! = ]]]L; !he ne&t hack solves this pro,le#
Go" let5s create a #acro to de)ine the enum declaration* Jde,ine .&x)%' x = % enu: ./PPAN76 K ./PPAN7_ I6+ L; Junde, . !he ne&t step is to de)ine the na#e to id nu#,er #apping* Jde,ine .&x)%' K%) JxL struct c:d_nu:#er_to_na:e K int c:d_nu:#er) char* c:d_na:e; L c:d_nu:#er_to_na:eTU = K ./PPAN7_ I6+ ) KN() N2 L Page 10> Copyright 2008, Steve Oualline
Steve Oualline
!he use o) nested #acros like this is e&tre#ely use)ul "hen it co#es dealing "ith data that #ust ,e e&pressed #ore than one "ay Our hacks have concentrated on enum de)initions, ,ut this hack has other uses ,eyond these si#ple progra##ing e&a#ples
Page 10?
C++ Hackers Guide in OP Jde,ine . !AN_0!+20N @ K close&in_,d';close&out_,d'; return; L Go" our if state#ent e&pands to* i, &done' K close&in_,d';close&out_,d'; return; L;
Steve Oualline
!his is not "hat "e intended One /solution3 is to enclose the state#ents
!his "orks Sort o) !he pro,le# is i) "e try an if 1 else state#ent* i, &done' . !AN_0!+20N; else not_done_%et&'; !his gives us a synta& error "hen "e try and co#pile it 6hyS $et5s look at the e&panded code* i, &done' K close&in_,d';close&out_,d'; return; L; else not_done_%et&'; !here5s an e&tra se#icolon on the line !his didn5t ,other us "hen there "as no else, ,ut no" that there is one, the co#piler gets con)used So ho" do "e de)ine a #ultiCstate#ent #acro that can ,e used like a state#entS The Hack: .se the do 1 .hile trick 9e)ine the #acro so the state#ents are inside a do 1 .hile loop* Jde,ine . !AN_0!+20N do K close&in_,d'; close&out_,d'; return; L while &;' @ @ @ @ @
Gotice that there is no se#icolon at a)ter the while &;' :nclosing #ultiple state#ents in a do 1 .hile loop #akes the# a single state#ent !hus they can ,e used any"here a single state#ent can ,e used
Page 10A
Steve Oualline
ote: !his is pro,a,ly the only place you legiti#ately "ant to use a do 1 .hile ;n all other cases a .hile loop is pro,a,ly si#pler and easier to understand than a do 1 .hile
Steve Oualline
!he sy#,ol 888 "as chosen ,ecause it5s easy to type and no one de)ines it 0Go one sane any"ay 2 @esides it5s shorter than
9:,0-,_I%DI.:TI%3_.$D-_I_:9_T:0I%3_$4T_:/_/$$%_:/_THI/_W$,0/
!he sy#,ol #akes the te#porary code stand out like a sore thu#, and it #akes it easy to take the code out "hen you5re done Yust search )or 888 and delete all the conditional code ,locks associated "ith it
Hack /3: Use 9i,de, on the #%nction =ot on the #%nction Call to Eliminate E&cess 9i,de,s
The Problem* (ou "ant to add so#e logging ,ut only )or the de,ug relase o) the so)t"are So throughout your code you have lots o) stu)) like this* Ji,de, 7!12" de#ug_:sg&!ntering ,unction sixth_le$el_o,_hell'; Jendi, /* 7!12" */ !his is ugly and annoying !here #ust ,e a ,etter "ay The Hack: ;) you de)ine de#ug_:sg right you can get rid o) all those &ifdef state#ents and #ake our code clean 'or e&a#ple* Ji,de, 7!12" extern $oid de#ug_:sg&const char* const :sg'; Jelse /* 7!12" */ static inline $oid de#ug_:sg&const char* const' KL Jendi, /* 7!12" */ Go" in the ,ody o) the code all "e have to Kust call the )unction* de#ug_:sg&!ntering ,unction sixth_le$el_o,_hell'; ;) 7!12" is de)ined, the real )unction is called ;) it5s not then the du##y de#ug_:sg is called Since it is an inline )unction, the opti#iFer "ill re#ove the code !he nice thing a,out this is that you don5t clutter up your code "ith useless &ifdef state#ents
Page 108
Steve Oualline
Hack /(: Create Code to Help Eliminate 9i,de, Statements #rom #%nction -odies
The Problem* (ou5re "riting a progra# )or #ultiple plat)or#s %s a result you have a lot o) 6ifdef state#ents sprinkled through out the code So #any in )act that they are #ake things look ugly and the code is hard to read 'or e&a#ple* $oid send_c:d&$oid' K send_c:d_start&'; Ji,de, 5!_+!S+20! send_texture&'; Jendi, /* 5!_+!S+20! */ Ji,de, 5!_./ /0 send_#ac8ground&'; i, &,oreground R= +0AN63A0!N+' send_,oreground&'; Jendi, /* 5!_./ /0 */ Ji,de, 5!_6I[! i, &si<e R= ;' send_si<e&'; Jendi, /* 5!_6I[! */ Ji,de, 5!_0!3 AG i, &pre$_c:d == '@;'' K pre$_c:d = cur_c:d; pre$_para: = cur_para:; L Jendi, /* 5!_0!3 AG */ send_c:d_end&'; L !his code is very di))icult to read !he 6ifdef directives ,reakup the logic o) the code The Hack* .se 6ifdef to de)ine out entire procedures only 'or e&a#ple, let5s take a look at the code*
Page 107
Steve Oualline
!his can ,e #uch si#pler 'irst "e use 6ifdef to control the de)inition o) the )unction send_te2tu(e* Ji,de, 5!_+!S+20! static $oid send_texture&' K // #od% o, the ,unction L Jelse inline static $oid send_texture&' K L Jendi, /* 5!_+!S+20! */ Go" )or the ,ody o) the code "e Kust put in a call to send_te2tu(e "ithout any 6ifdef $oid send_c:d&$oid' K send_c:d_start&'; send_texture&'; 6e can do the sa#e thing "ith set_#a;5g(ound and set_fo(eg(ound !he calls to these )unctions look like* send_#ac8ground&'; i, &,oreground R= +0AN63A0!N+' send_,oreground&'; @ut doesn5t this cause e&tra code to ,e put in our procedureS 6hat a,out the state#entS i, &,oreground R= +0AN63A0!N+' %ctually i) the ,ody o) sendJ)oreground is de)ined out, the opti#iFer "ill re#ove this state#ent Go" let5s look at the code Ji,de, 5!_0!3 AG i, &pre$_c:d == '@;'' K pre$_c:d = cur_c:d; pre$_para: = cur_para:; L Jendi, /* 5!_0!3 AG */
Page 110
Steve Oualline
!o get rid o) this 6ifdef "e )irst put the code in a procedure* Ji,de, 5!_0!3 AG static inline $oid do_repla%&' K i, &pre$_c:d == '@;'' K pre$_c:d = cur_c:d; pre$_para: = cur_para:; L L Jelse /* 5!_0!3 AG */ static inline $oid do_repla%&' K // 7o nothing L Jendi, /* 5!_0!3 AG */ Go" "e can Kust put a )unction call in our code* do_repla%&'; !he key to this hack is using &ifdef to change the de)inition o) entire )unctions Since )unctions are a si#ple, logical unit o) code, "e are de)ining things in or out at the unit level !he old "ay changed the progra# at the state#ent level and "as #uch #ore con)using !ake a look at ho" #uch si#pler the ,ody o) our )unction is "hen "e use this hack* $oid send_c:d&$oid' K send_c:d_start&'; send_texture&'; send_#ac8ground&'; i, &,oreground R= +0AN63A0!N+' send_,oreground&'; i, &si<e R= ;' send_si<e&'; do_repla%&'; send_c:d_end&'; L
Page 111
Steve Oualline
The Problem: !here5s no shortage o) people "ho have a great idea a,out ho" to speed up the ,uild !hey have all sorts o) reasons "hy their pet idea "ill let you co#plete a )ive day ,uild in 4 8 seconds 'or e&a#ple, the gcc co#piler has the -pipe option Gor#ally the co#piler "ill run the )irst pass o) the co#piler and "rite the output to a te#porary )ile !hen pass 2 "ill read this )ile and "rite a second te#porary %nd so on )or ho"ever #any passes are needed 6ith the -pipe option every pass is run at the sa#e ti#e the output o) one connected to the input o) the ne&t through a pipe !he theory is that ,y doing this you eli#inate the te#porary )ile, the disk ;1O )or the te#porary )ile and do everything in #e#ory So the -pipe option #ust #ake things )aster %nd i) "e needed #ore convincing "e can take a look at the kernel 8ake)iles and )ind that the option is used there and i) the $inu& kernel uses it, then it #ust ,e good The Hack: % good hacker tests the /o,vious3 ,ecause so#eti#es the /o,vious3 isn5t o,vious $et5s take the case o) the Cpipe option Co#piling a kernel "ithout the
-pipe option takes ?B*0> 6ith the -pipe it takes ?B*17 6ait a second, it took longer "ith -pipe $et5s do a )e" #ore tests*
Page 112
Steve Oualline
o Pipe
?B*0> ?B*0> ?A*?8 ?A*?? ?A*?>
Pipe
?B*17 ?A*18 ?A*17 ?A*1B ?A*21
'ro# this "e can see that -pipe does not #ake things )aster ;) anything it #akes the# slo"er Go" there could ,e a nu#,er o) reasons )or these results 'irst o) all disk ;1O is ,u))ered and $inu& uses lots o) ,u))ers ;t could ,e that the te#porary )iles e&ist entirely in #e#ory and never #ake it to the disk %lso there could ,e di))erent logic in the co#piler passes )or pipe 1 nonCpipe input strea#s @ut ulti#ately as hackers all "e5re concerned "ith is results and the results do not support the theory !here are lots o) cases in progra##ing "here theory and reality do not #atch $ots o) people kno" "here the slo" parts o) their code is Hackers test ,y using a pro)iler % data,ase #anuals says that inserting records, then adding an inde& is )aster than inserting inde&ed records % hacker tests So#eti#es you )ind out that the #anual is "rong %)ter all one o) the #arks o) a true hacker is so#eone "ho kno"s progra##ing and co#puters )ront"ards and ,ack"ards !hey not only kno" "hat the #anual says "ith "ork, ,ut also kno" i) the #anual is right or not The Congreve Clock ; a# into horology14 and one o) #y )avorite types o) clocks "as designed ,y Sir 6illia# Congreve 01BB2 Q 18282 Sir 6illia# is ,est kno"s )or his contri,ution to the Star Spangled @anner ;) you re#e#,er the line /and the rockets red glare,3 he invented the rockets
Page 114
Steve Oualline
9uring the ti#e that he lived one o) the great engineering challenges "as #aking a accurate clock Sir 6illia# "as a proli)ic inventor and turned his genius to the pro,le# o) creating a highly accurate clock !icking is one o) the #aKor sources o) insta,ility and inaccuracy in a clock !he #ove#ent o) gears is a pro,le# and the less they #ove the ,etter One "ay to solve this pro,le# is ,y using a very long pendulu# ;n )act the longer the ,etter Congreve ca#e up "ith another solution !he result "as the Congreve Clock or the :&tre#e 9etached :scape#ent Clock as he called it % ,all is dropped on an inclined plane and allo"ed to roll do"n a track 6hen it reaches the end it trips a lever and the plane tilts the other "ay the the ,all rolls do"n to the other end !his process can take 1? to 40 seconds depending on the clock Congreve calculated that his clock design "as the e=uivalent or a conventional clock "ith a si&ty )oot pendulu# %s a result his clock should ,e accurate to "ithin a second a #onth Go" 6illia# Congreve "as a #aKor inventor, engineer, and scientist He had a great deal o) logic and calculations to ,ack up his clai# !he design "as per)ect and the engineering i#pecca,le :&tensive though and design "ent into creating the super accurate Congreve Clock :&cept it didn5t "ork !urns out that "hile a pendulu#s has a natural )re=uency a ,all rolling do"n a path does not :very speck o) dust, every te#perature change caused inaccuracy in the clock %nd ; "on5t even go into the other pro,le#s "ith his design !he goal "as )or a clock "ith an error rate o) less than a second a #onth @ut in )act a good Congreve Clock is only accurate to a,out t"enty #inutes a day
Page 11>
Steve Oualline
Page 11?
Steve Oualline
!he GG. #ake co##and 0installed as g#ake on #ost syste#s2 has an option to help #ake opti#al use o) #ultiple processor syste#s !he -j< )lag tell the #ake progra# to try and do t"o co#piles at the sa#e ti#e ;deally this should result in cutting the co#pile ti#e in t"o !here are so#e li#itations to this syste# 'irst o) all it5s possi,le )or co#pilation errors to appear out o) order 'or e&a#ple, nor#ally i) out co#pile the )iles alpah cpp and ,eta cpp you #ight see* alpha=cpp:?: 6%ntax error alpha=cpp:D: Another s%ntax error #eta=cpp:?: 6%ntax error #eta=cpp:D: 6crewed up again 6ith -j< you #ight see* alpha=cpp:?: 6%ntax error #eta=cpp:?: 6%ntax error alpha=cpp:D: Another s%ntax error #eta=cpp:D: 6crewed up again !he other pro,le# is that ,adly )or#ed 8ake)iles #ay "hen you use -j< 0or higher2 @ut is -j< really e))ective or is it Kust another -pipeS !ests sho" that on a dual processor syste# -j< actually does "ork Here5s the results*
o 23
?A*17 ?A*18 ?A*17 ?A*1B ?A*21
23"
27*>B 27*>4 27*>8 27*>2 27*>>
23$
27*48 27*>? 27*>4 27*>2 27*>?
Go" Kust ,ecause it "orks on #y syste# doesn5t #ean it "ill "ork on yours @ut "ith a little e&peri#entation you should ,e a,le to )ind the opti#al #ake settings (4treme Parallel Processing Hackers al"ays "ant to kno" ho" the syste# ,ehaves in e&tre#e conditions !he -j< and -j= s"itches are rather #ild !hey "ill only start t"o or )our Ko,s 6hat happens i) "e increase the nu#,er
Page 11A
Steve Oualline
;) no nu#,er is supplied and you Kust -j alone, g#ake "ill start as #any Ko,s as possi,le at the sa#e ti#e ; tried this once on a #aKor piece o) so)t"are ;t "as the only ti#e ; ever sa" the load average go a,ove 1,0001> ;5# not sure ho" #uch higher the load average "ent ,ecause at that point the syste# #onitoring tools started to hang 0!hey couldn5t get any CP. cycles 2 !he syste# "as o,viously paging like craFy and really ,eating up the disk O,viously trashing1? "as going on and killing the syste#, so at this point ; re,ooted 0Couldn5t kill the processes ,ecause the shell couldn5t get enough CP. to #ake a di))erence 2
Page 11B
Steve Oualline
!o use the ccache progra# si#ply insert the ccache co##and ,e)ore each co#plication progra# in your 8ake)iles 'or e&a#ple* hello=o: hello=cc ccache gcc Ng Nc hello=cc 6hen this progra# is e&ecuted ccache "ill per)or# the )ollo"ing operations* 1 -un the )ile hello cc through the preCprocessor 2 Check the #d?su# o) the result against any stored checksu# )ound in the cache directory 4 ;) a #atch is )ound, the o,Kect is supplied )ro# the cache > Other"ise the co#piler is run and the results stored in the cache )or )uture use !here are a huge nu#,er o) details that have ,een glossed over, ,ut that5s the ,asic idea !he ccache progra# is a si#ple and very e))ective "ay o) speeding up repeated ,uilds !he ccache progra# is availa,le )ro# http*11ccache sa#,a org
Steve Oualline
;t then per)or#s the nor#al operations Kust as i) you and edited the 8ake)ile and added a ccache co##and to each co#pilation rule ote: (ou pro,a,ly "ant to add the P%!H co##ands to your pro)ile or ,ashrc so they are e&ecuted each ti#e you start a ne" shell
Page 117
Steve Oualline
Page 120
Steve Oualline
$et5s assu#e that you didn5t take the advice in the previous hack and have decided that you #ust opti#iFe Go" you #ust decide "hat part o) your progra# you5re going to try and #ake )aster ;n #ost progra#s there are one or t"o )unctions "hich consu#e a,out 70\ o) the CP. 8any ti#es a progra##er "ill have a good )eel )or "here his progra# is getting stuck @ut #ore o)ten than not it "ill turn out that his )eeling does not agree "ith realist %s a result i) he goes "ith his )eelings he "ill "ind up opti#iFing the "rong code and not speeding up his progra# The Hack: .se the Pro)iler !he pro)iler tells you "hich )unctions are taking up the #ost ti#e ;n #y e&perience a typical pro)iling session goes like this* ;5# in)or#ed that the )ile save )unction is taking too long ; have an idea that the logic that converts the para#eters to te&t )or saving #ay ,e the progra# %)ter all the code "as not designed to ,e e))icient and it certainly )ul)illed that design criteria So ; start up #y trusty pro)iler and try and locate the pro,le# in the save logic @ut so#ething )unny happens along the "ay !urns out that save is taking only 1110 o) the ti#e !he other 70\ is in the sorting )unction !urns out that in order to get things ready )or the save "e sort the para#eters Yust to #ake sure that they are sorted, every level o) the code sorts the# ,e)ore calling the ne&t lo"er level ;n all there are t"entyC)ive sorts done on the sa#e data !he )irst sort puts things in order and the other t"entyC)our Kust "aste ti#e 8y choice at this point is sort less o)ten or #ake sort #ore e))icient ; decide to add a )lag "hich tells #e i) the para#eter list is sorted or not !he sort )unction checks that )lag and does nothing i) the list is in order Pro,le# solved Gotice that the pro,le# "as not "here ; e&pected it to ,e ;t "as in so#e other code, "hich ; didn5t "rite ,y the "ay, "hich "as terri,ly ine))icient Had ; gone "ith #y instinct and opti#iFed the save code, ; "ould not have #ade the progra# any )aster !he #oral o) this store is use the pro)iler ;t tells you "here the code really is slo" rather than "here you think it5s slo"
Page 121
Steve Oualline
Page 122
C++ Hackers Guide static $oid two_digits&const int i' K i, &i H= (;' K putc&&i / (;' M ';''; L putc&&i \ (;' M ';''; L ,or &int i = ;; i C *;; MMi' K puts&I is '; two_digits&i'; putc&'@;''; L
Steve Oualline
;t should ,e noted that the second, opti#iFed, version is #uch longer and #ore co#ple& than the )irst one 6hat "e5ve done is replace slo" general purpose code "ith special purpose code designed )or this speci)ic task ;t5s )aster, ,ut it5s #ore co#ple& and #ore likely to contain ,ugs %gain only opti#iFe i) you #ust 0See Hack 80 a,ove 2
Page 124
C++ Hackers Guide 1 ;ncre#ent the varia,le 2 -eturn the incre#ented result !he post)i& version 02++2 per)or#s the )ollo"ing* 1 Save a copy o) the original value 2 ;ncre#ent the varia,le 4 -eturn the unincre#ented copy you saved in step 1
Steve Oualline
So )or the post)i& 02++2 version you have to #ake a copy o) the varia,le !his can ,e a costly operation $et5s take a look at ho" a typical class #ight i#ple#ent these t"o operations* class ,ixed_point K // 2sual stu,, // 3re,ix &MMx' operator ,ixed_point operator MM&' K $alue M= 5IS!7_N2P1!0_/N!; return &*this'; L // 3ost,ix &xMM' operator ,ixed_point operator MM&int' K // !xtra wor8 needed ,ixed_point result&this'; $alue M= 5IS!7_N2P1!0_/N!; return &result'; L 'or this reason al"ays use the pre)i& version o) the incre#ent and decre#ent operators to #ake your progra# #ore e))icient
Hack 2(: 8ptimi<e I?8 0! Usin* the C I?8 7'I Instead o, the CKK 8ne
;t should ,e noted that this opti#iFation is co#piler dependent Ho"ever, every co#piler ;5ve used e&hi,its this ,ehavior The Problem: !he C++ ;1O strea# is #ore )le&i,le and less error prone than it5s C counterpart @ut )or #ost syste#s, it5s also slo"er Page 12> Copyright 2008, Steve Oualline
Steve Oualline
Consider a progra# designed to read a )ile line ,y line and "rite it to standard out !he C++ version is* Jinclude Ciostrea:H int :ain&' K char lineTF;;;U; while &(' K i, &R std::cin=getline&line) si<eo,&line''' #rea8; std::cout CC line CC std::endl; L return&;'; L !he C version is* Jinclude Cstdio=hH int :ain&' K char lineTF;;;U; while &(' K i, &,gets&line) si<eo,&line') stdin' == N2 #rea8; ,puts&line) stdout'; L return &;'; L ;t takes 78 seconds )or the C++ progra# to copy a ,unch o) )iles to /dev/null "hile it takes the C progra# only 11 seconds to do the sa#e thing 1A The Hack: .se C ;1O in a C++ progra# "hen ;1O speed is an issue !his hack does speed up ;1O ,ound progra#s, ,ut it should ,e used "ith caution 'irst you do loose the advantages o) the C++ ;1O syste# !his includes the increased sa)ety that co#es )ro# this syste# '
1A On a $inu& syste# using GCC Eersion 4 >,4, @ut you5re a hacker Q run your o"n tests
Page 12?
Steve Oualline
%lso the ti#ing tests presented here co#e )ro# one co#piler on one co#puter syste# (ou should per)or# si#ilar tests using your progra##ing environ#ent 6ho kno"s your co#piler #ay ,e ,etter
Hack 2+: Use a Local Cache to 71oid Recomp%tin* the Same Res%lt
The Problem: (ou have a )unction that is called repeatedly to co#pute the sa#e values !his )unction is taking a long ti#e to do its Ko, Ho" can you #ake things )asterS $et5s take a look at an e&a#ple @elo" is a (e;tangle class !he )unction ;ompute_se(ial returns a uni=ue serial string "hich is used )or sorting the shapes classes class rectangle K pri$ate: int color; int width; int height; rectangle&int i_color) int i_width) int i_height': color&i_color') width&i_width') height&i_height' KL $oid set_color&int the_color' K color = the_color; L char serial_stringT(;;U; // 2niYue I7 string char* get_serial&' K snprint,&serial_string) si<eo,&serial_string') rectN\d x \d / \d) width) height) color'; return &serial_string'; L :&a#ination o) this class sho"s that it uses the snp(intf to co#pute the serial string !his is an e&tre#ely costly )unction to use 6e need opti#iFe out this )unction i) at all possi,le The Hack: .se a local cache % s#all local cache can ,e very use)ul "hen it co#es to avoid the pro,le# o) co#puting the sa#e thing over and over again
Page 12A
Steve Oualline
'or our (e;tangle class this is acco#plished "ith so#e si#ple changes to get_se(ial )unction* char* get_serial&' K i, &dirt%' K snprint,&serial_string) si<eo,&serial_string') rectN\d x \d / \d) width) height) color'; dirt% = ,alse; L return &serial_string'; L Go" all "e have to do is #ake sure that di(t> is set any ti#e the data used to co#pute the serialJstring is changed !his includes the constructor* rectangle&int i_color) int i_width) int i_height': color&i_color') width&i_width') height&i_height') dirt%&true' KL %ny )unction "hich changes any o) the key #e#,ers #ust ,e changed as "ell* $oid set_color&int the_color' K color = the_color; dirt% = true; L !his hack trades co#ple&ity )or speed @y #aking the class #ore co#ple&, "e can #ake it )aster So this hack should ,e used "ith care (ou should only use it a)ter you5ve run your progra# through a pro)iler and #ade sure that this class is one o) the ,ottlenecks 'ar too o)ten people "ho think they are hackers opti#iFe a progra# "here they think there5s a speed pro,le# only to )ind out that they are not real hackers and don5t have a speed pro,le# "here they think they do Pro)ilers identi)y real speed pro,le#s, that5s "hy they are used )re=uently ,y real hackers !here is a price to ,e paid )or using this hack % real hackers kno"s "hen the price is "orth it
Page 12B
Steve Oualline
Steve Oualline
;) you do not understand e&actly "hat ; Kust said, the don5t do this opti#iFation until you do ; suggest you per)or# so#e e&peri#ents "ith custo# ne. 1 delete operator using ,oth ,ase and derived classes 9o not try this hack in production code unless you )ully understand "hat is going onN 6e are going to assu#e that progra# allocates #ostly varia,les o) type sy#,ol and that5s "hat "e "ant to opti#iFe @ut Kust in case so#eone decided to e&tend our class, "e check the siFe i, &si<e == si<eo,&s%:#ol'' K ;) the siFe is not right, "e5ll )all through to the ,otto# o) the progra# and use the syste# ne" to allocate the #e#ory return &::new charTsi<eU'; ;) the correct siFe is given to use, that #eans "e are allocating a ne" s>m#ol so "e can use the opti#iFed #e#ory allocation* i, &si<e == si<eo,&s%:#ol'' K $oid* ptr = local_allocate&si<e'; 6e5ll leave the i#ple#entation o) lo;al_allo;ate to you ;t should ,e si#ple and )ast 0;) it5s ,ig a slo", "hat5s the point o) using itS2 'or e&a#ple, the allocator could use a )i&ed #e#ory array to hold the data Since you have a )i&ed siFe ite# and kno" so#ething a,out the e&pected allocate 1 )ree usage you should ,e a,le to #ake a very e))icient #e#ory #anager 6henever "e do a custo# ne. "e need to do a custo# delete as "ell* static $oid delete&$oid* const ptr' K i, &local_delete&ptr'' return; ::delete ptr L One )inal note, read the ne&t antiChack ,e)ore proceeding
Page 127
Steve Oualline
8ost o) the ti#e i) you add in an opti#iFation "ithout running the progra# through a pro)iler and care)ully analyFing it, you "ill opti#iFe in the "rong place !he ne. 1 delete hack is tricky and dangerous (ou don5t "ant to add it unless you kno" that it "ill speed up your progra# !hat #eans you have to do your ho#e"ork 'ar too o)ten a person "ho thinks he5s a hacker, ,ut isn5t "ill per)or# the local ne. 5 delete % predicta,le series o) results generally )ollo"s 'irst the code ,reaks !hat5s ,ecause getting local ne. 5 delete operators to )unction right is tricky 0See the previous hack )or details 2 @ecause the progra##er has i#ple#ented ne. 1 delete "rong his progra# )ails in #ysterious "ays !racking these do"n takes ti#e :ventually he "ill give up or )inally get a "orking local ne. 5 delete O) course the proKect "ill )all ,ehind schedule during this process %)ter he )inally gets the ne" #e#ory #anage#ent syste# de,ugged, he "ill discover that ,ecause he didn5t do his ho#e"ork and run a pro)iler, he Kust sped up class that not part o) the ti#e critical progra# )lo" !hus the result is that the progra# is not any )aster than "hen he started So the only thing he has to sho" )or his e))ort is a skipped schedule @ut "hat did he gainS He learned a i#portant lesson in pre#ature opti#iFation % lesson you don5t have to learn the hard "ay ,ecause you read this antiChack
Page 140
Steve Oualline
People =uickly discovered that you could use shi)t instead o) #ultiply 0or divide2 "hen using a po"er o) 2 02,>,8,1A 2 !he resulting code "as #uch )aster @ut #achines have i#proved and so has co#piler technology ;) you need to do a #ultiply, do a #ultiply !he co#piler "ill generate the )astest code possi,le to acco#plish this operation %ll you do "hen using a shi)t instead o) a #ultiply or divide is #aking your code #ore o,scure 6e5ve got "ay too #uch o,scure code no", ,e clear and si#ple .se #ultiple to #ultiply and divide to divide
t?i;e @ut ,ody cpp does not kno" that the t"ice is an inline )unction ;t5s
going to call it Kust like a nor#al e4tern )unction
;n this case it5s per)ectly legal )or the )ile ,ody cpp to contain a call to
Page 141
Steve Oualline
So the co#piler is )orced to not only generate all the inCline instances o)
t?i;e, ,ut also generate standard )unction code Kust in case so#eone )ro#
outside tries to call it 9eclaring the )unction static tells the co#piler that no one )ro# the outside is going to call this )unction and let5s it sa)ely eli#inate the standard )unction code !hus saving a )e" ,ytes
Hack 35: Use do%0le Instead o, #loat #aster 8perations When :o% Don6t Ha1e 7 #loatin* 'oint 'rocessor
The Problem: (ou are "riting code )or an e#,edded syste# and you have to use real nu#,ers ;s there a si#ple "ay o) speeding things upS The Hack* .se double instead o) float ;t5s )aster %t )irst glance this advice see#s silly :veryone kno"s that double contains #ore ,its than float there)ore it is /o,vious3 that using double is going to take longer than float .n)ortunately the "ords /o,vious3 and /progra#ing3 )re=uently inco#pati,le !he C and C++ standard states that all real arith#etic is to ,e done in double $et5s take a look at "hat goes on under the hood o) the )ollo"ing code* ,loat a)#)c; a = (=;; # = *=;; c = a M #; !he steps needed ,y the addition are* 1 Covert a to double 2 Covert # to double 4 %dd the double version o) a to the double version o) # > Convert the result to float ? Store the result in ; Conversion )ro# float to double and double to float are not cheap and all the conversions take ti#e Go" let5s look at "hat goes on "hen "e change the varia,les to double
Page 142
Steve Oualline
!hree float 1 double conversions have ,een re#oved Since a )loating point conversion operation is e&pensive, the result is that the code using double is #uch )aster than float version @e "arned, this hack "ill not "ork on all #achines ;n particular it "ill not "ork on PCs and other #achine "hich have a )loating point processor 0!hat5s "hy "e said "e "ere doing an e#,edded progra# "hen "e descri,ed the pro,le# 2 Hard"are )loating point units al#ost al"ays convert any nu#,ers to an internal )or#at ,e)ore doing the arith#etic no #atter )or#at is used 0So#e co#pilers use the long double type to represent this )or#at 2 S#aller, e#,edded processors don5t have the lu&ury o) )loating point units so they use a so)t"are li,rary )or their )loating point ;) this is the case )or the syste# you5re "orking on, this hack "ill pro,a,ly "ork (ou should al"ays test this hack ,e)ore trying it 'loating point operations have a li)e o) their o"n and can do strange things to unsuspecting code
Hack 31: )ell the Compiler to -reak the Standard and #orce it )o )reat ,loat as ,loat When Doin* 7rithmetic
The Problem* (ou have to use )loating point on an e#,edded syste# and can a))ord the e&tra storage needed to store all the values a double Ho" can you speed things upS The Hack: !ell the co#piler to ,reak the standard -ead your co#piler docu#entation 8ost co#pilers have an option that lets you generate single precision arith#etic even though the standard calls )or dou,le precision 'or the gnu gcc co#piler this option is -fallo?-single-p(e;ision 6hen this option is ena,led then adding t"o single precision nu#,ers is done ,y adding the t"o nu#,ers Got converting, adding, and converting ,ack !urning this on #akes your progra# e&ecute #uch )aster "ith very little loss o) precision
Page 144
Steve Oualline
%gain, as "e5ve discussed in the last hack, this only "orks "hen you are not using a #achine "ith a )loating point processor 6hen hard"are is used, the hard"are does it5s o"n thing concerning conversions, so the co#piler option has no e))ect
Page 14>
Steve Oualline
!he #ath is actually )airly si#ple .n)ortunately ,ecause o) C++ rich operator set, you have to de)ine a lot o) operators !he code at the end o) this hack contains a li#ited i#ple#entation o) a si#ple )i&ed point class One )inal note, in this e&a#ple, "e use a )i&ed deci#al point t"o places to the le)t !he syste# "ould ,e a lot )aster i) "e used a )i&ed ,inary point B places to the le)t ;n other "ords, a conversion )actor o) 128 is #uch )aster than 100 ;t gives us the sa#e precision at slightly ,etter speed Jinclude Costrea:H class ,ixed_point K pri$ate: // 5actor that deter:ines where // the ,ixed point is static const unsigned int 5IS!7_5A.+/0 = (;;; // 7e,ine the data t%pe we are using ,or // the i:ple:entation t%pede, short int ,ixed_i:ple:entation; pri$ate: // +he $alue o, the nu:#er ,ixed_i:ple:entation $alue; pu#lic: // 7e,ault $alue is ; when // constructed with no de,ault ,ixed_point&' : $alue&;' KL // .op% constructor ,ixed_point&const ,ixed_point> other' : $alue&other=$alue' KL // et the user suppl% us a dou#le as well ,ixed_point&dou#le d_$alue' : $alue& static_castC,ixed_i:ple:entationH& d_$alue / static_castCdou#leH&5IS!7_5A.+/0'' ' KL // et the user initiali<ed with an integer ,ixed_point&int i_$alue' : $alue&i_$alue * 5IS!7_5A.+/0 ' Page 14? Copyright 2008, Steve Oualline
C++ Hackers Guide KL ,ixed_point&long int i_$alue' : $alue&i_$alue * 5IS!7_5A.+/0 ' KL // All the usual assign:ent operators ,ixed_point> operator = &const ,ixed_point> other' K $alue= other=$alue; return *this; L ,ixed_point> operator = &,loat other' K $alue = ,ixed_point&other'=$alue; return *this; L ,ixed_point> operator = &dou#le other' K $alue= ,ixed_point&other'=$alue; return *this; L ,ixed_point> operator = &int other' K $alue= ,ixed_point&other'=$alue; return *this; L ,ixed_point> operator = &long other' K $alue = ,ixed_point&other'=$alue; return *this; L
Steve Oualline
// .on$ersion operators operator dou#le&' const K return static_castCdou#leH&$alue' / static_castCdou#leH&5IS!7_5A.+/0'; L operator short int&' const K return $alue / 5IS!7_5A.+/0; L operator int&' const K return $alue / 5IS!7_5A.+/0; L operator long&' const K Page 14A Copyright 2008, Steve Oualline
C++ Hackers Guide return $alue / 5IS!7_5A.+/0; L // 2nar% operators ,ixed_point operator M&' const K return *this; L ,ixed_point operator N&' const K ,ixed_point result&*this'; result=$alue = Nresult=$alue; return result; L
Steve Oualline
// 1inar% operators ,ixed_point operator M & const ,ixed_point> other' const K ,ixed_point result&*this'; result=$alue M= $alue; return &*this'; L ,ixed_point operator N & const ,ixed_point> other' const K ,ixed_point result&*this'; result=$alue N= $alue; return &*this'; L ,ixed_point operator * & const ,ixed_point> other' const K ,ixed_point result&*this'; result=$alue *= $alue; result=$alue /= 5IS!7_5A.+/0; return &*this'; L ,ixed_point operator / & const ,ixed_point> other' const K ,ixed_point result&*this'; result=$alue *= 5IS!7_5A.+/0; result=$alue /= $alue; return &*this'; L // .o:parison operators #ool operator == & const ,ixed_point> other' const K Page 14B Copyright 2008, Steve Oualline
Steve Oualline
return $alue == other=$alue; L #ool operator R= & const ,ixed_point> other' const K return $alue R= other=$alue; L #ool operator C= & const ,ixed_point> other' const K return $alue C= other=$alue; L #ool operator H= & const ,ixed_point> other' const K return $alue H= other=$alue; L #ool operator C & const ,ixed_point> other' const K return $alue C other=$alue; L #ool operator H & const ,ixed_point> other' const K return $alue H other=$alue; L ,riend std::ostrea:> operator CC & std::ostrea:> out) const ,ixed_point> nu:#er'; L; // Wuic8 and dirt% output operator= std::ostrea:> operator CC & std::ostrea:> out) const ,ixed_point> nu:#er' K out CC static_castCconst dou#leH&nu:#er'; return &out'; L
Steve Oualline
;n this Hack 72 "e started "ith pi&els represented ,y float and replaced it "ith a fi2ed_point i#ple#entation @oth versions should produce the sa#e result @ut as hackers "e kno" that there5s a vast di))erence ,et"een /should3 and /is3 !hat5s "here testing co#es in % good test to see i) the opti#iFation "as correct is to run the unopti#iFed progra# and save the results !hen run the opti#iFed version and check to see that "e get the sa#e results ;n real li)e Hack 72 "as used to speed up a sophisticated dithering algorith# )or a color inkKet printer 6hen a ,inary co#parison "as done on the output the result "ere di))erent So in spite o) "hat our high po"ered nu#erical analysis e&pert said, t"o digits "ere not enough to generate identical results Ho"ever "hen the test i#ages "ere printed, the opti#iFed results looked Kust as good to the Print Co##ittee as the unopti#iFed versions So the co#puter could tell the di))erence ,et"een the t"o algorith#s ,ut the Print Co##ittee could not ;n the inkKet ,usiness, the Print Co##ittee rules so "e kept the ne"er, )aster algorith# !here5s a #oral to this story and as soon an ; )igure out "hat it is ;5ll put it in this ,ook
Page 147
Steve Oualline
; once opti#iFed a progra# that "as taking 20 hours per run do"n to the point "here it "as taking a,out 8 seconds per run Go" ;5# a good hacker, ,ut ;5# not that good !he original progra# "as very ,adly "ritten ;n de)ense o) the original progra##er, it "as the )irst progra# he had ever "ritten and he did a re#arka,ly Ko, o) i#ple#enting a sophisticated cryptographic algorith# despite not kno"ing #any ,asic )eatures o) the C language !he #its_to_#>tes )unction "as targeted )or a cell phone 0%-8 processor2 -unning the code through the co#piler and taking a look at the asse#,ly code "e )ind so#e interesting things going on 'or e&a#ple the i#ple#entation o) the line* short int #%tes = #its / A; !he generated code looks like* :o$w r() #its asr r() ? lsl r() (E asr r() (E ; ; ; ; r( r( r( r( &#%tes' = r* HH = r( CC = r( HH = #its ? &a8a r( = r(/A' (E &_' (E &_'
6hat5s going on "ith the t"o )unny instructions that shi)t the result le)t ,y 1A then right ,y 1AS %t )irst glance this is a rather useless piece o) code !he processor uses 42 ,it arith#etic On this #achine a short int is 1A ,its 6hen the syste# does the divide ,y 8 a 42 ,it result is generated So the co#piler generates t"o instruction designed to convert a 42 ,it value into a 1A ,it one !his occurs a)ter the divide and a)ter the incre#ent !his gives us a total o) > useless instructions Changing the )unction to use int instead o) short int eli#inates these instructions and #akes our code )aster !he ne&t step is to see i) "e can "rite a ,etter algorith# and eli#inate that conditional* int #its_to_#%tes&int #its' K return &#its M D' / A; L !his co#pletely eli#inates all the conditional logic an saves us a )e" #ore instructions Go" the actual ,ody o) the )unction is Kust a hand )ull o) instructions Can "e cut it do"n even #oreS
Page 1>0
Steve Oualline
Ho" a,out cutting it do"n to 0 instructionsS ;t5s possi,le %ll "e have to is to add the inline key"ord* inline int #its_to_#%tes&int #its' K return &#its M D' / A; L Go" "hen the opti#iFer sees a line like* store_si<e = #its_to_#%tes&B('; it "ill opti#iFe it do"n to] store_si<e = E; !he )unction is not even called %ll the co#putations are ,eing done at co#pile ti#e @ut "e5re not done opti#iFing !here5s a di))erence ,et"een a )unction declared inline and one declared static inline 6hen a )unction is declared inline the co#piler "ill inline all the )unction calls it sees, then generate a regular nonCinline )unction ,ody in case so#eone )ro# the outside "ants to call this )unction !o counter this "e declare our )unction static inline and stick it in a header )ile !hus saving us a couple o) doFen ,ytes in this e&a#ple Q total Q in a 4 ?8@ progra# Go" as hackers there5s one #ore thing "e need to consider 6hat happens "hen things go "rong %)ter all "e never trust the caller to do things right and the "e can ,e called "ith a negative nu#,er 6e need to ans"er the =uestion /Ho" #uch storage does -8@ ,its take upS3 !he easiest thing to do is to assu#e that this "ill never happen and Kust ignore it @ut i) "e do this "e need to docu#ent the )act in the progra# /* * #its_to_#%tes V "i$en a nu:#er o, #its) return the * nu:#er o, #%tes needed to store the:= * * -A0NIN": +his ,unction does no error chec8ing so * i, %ou gi$e it a $er% wrong $alue %ou get a $er% wrong * result= */ %ssu#ing so#ething ,ad "ill never happen is not really a good idea %s hackers "e kno" that lots o) things that can /never happen3 actually do Checking )or the /i#possi,le3 usually a good idea Page 1>1 Copyright 2008, Steve Oualline
C++ Hackers Guide 'or e&a#ple, "e could insert an asse(t state#ent* static inline int #its_to_#%tes&int #its' K assert&#its H= ;'; return &#its M D' / A; L
Steve Oualline
!he pro,le# "ith asse(t state#ents is that they cause the progra# to a,ort ;n real li)e this code lived in a #o,ile phone and a )ailed asse(t "ould cause the phone to reset !his "as not good ,ecause "hen this happened the phone reset it "ould play the /"elco#e sound3 :nd users "ere "ondering "hy their phone "ould restart )or /no reason at all3 !he phone #aker5s /solution3 to this pro,le# "as si#ple !hey changed the code so that a a )ailed asse(t restarted the phone silently !he code "as still very ,uggy, ,ut the ,ugs ,eca#e less visi,le 0audi,leS2 to the end users %lso you should re#e#,er that assertions can ,e co#piled out, so this code provides no protection at all Since this is C++ thro"ing an e&ception is one "ay o) handling the error* static inline int #its_to_#%tes&int #its' K i, &#its C ;' throw&:e:or%_error&#its_to_#%tes'; return &#its M D' / A; L !hese error checking options are e&pensive One ine&pensive thing "e can do is to #ake sure that error can never happen Ho" do "e do thatS %ll "e have to is #ake the argu#ent 0and the return value2 unsigned6 static inline unsigned int #its_to_#%tes&unsigned int #its' K return &#its M D' / A; L 'inally there5s one #ore "ay o) dealing "ith this error Yust change the )unction to silently ignore it and return a de)ault value* static inline int #its_to_#%tes&int #its' K i, &#its C ;' return &;'; return &#its M D' / A; L
Page 1>2
Steve Oualline
!his is usually not a good idea since such code tends to hide errors in other pieces o) code ;n general you don5t "ant to silently )i& things 8ay,e output a log #essage* static inline int #its_to_#%tes&int #its' K i, &#its C ;' K log_error& Illegal para:eter in #its_to_#%tes&\d') #its'; log_error&6tandard ,ixup ta8en'; return &;'; L return &#its M D' / A; L ;n e&a#ining ,itsJtoJ,ytes "e can see that it is actually a very short )unction @ut it does illustrate so#e o) the things good hackers consider "hen "orking "ith code !hese include*
<no"ing ho" the co#piler generates code and designing your code to #ake opti#al use o) this in)or#ation
8aking #a&i#u# use o) the language )eatures such as inline and static inline
!here5s a lot to ,e learned )ro# this little progra# %s hackers "e5re al"ays learning 6e study, research, e&peri#ent, and play all to gain a ,etter understanding o) the progra##ing process
1B Yust ,ecause you5re paranoid doesn5t #ean they aren5t out to get you
Page 1>4
Steve Oualline
18 'or the hu#or i#paired, ;5# e&aggerating % real hacker "ould split up so#ething this ,ig into #ultiple s#aller and #ore #anagea,le structures
Page 1>>
Steve Oualline
!he gcc co#piler has a nonCstandard e&tension that lets you na#e the )ields in an initialiFation state#ents 'or e&a#ple* $er%_large so:ething_#ig = K =si<e = 6I[!_1I") =,ont = 5/N+_+IP!6) =color = ./ /0_1 A.4) // ()]]D :ore ite:s; L; @y na#ing things "e decrease the risk o) getting so#ething in the "rong order !he pro,le# is that "e have created a nonCstandard progra# @ut unless your dealing "ith a very unusual plat)or#, there is a gcc co#piler )or your syste# @ut there is one pro,le# "ith this syste# ;t is possi,le to o#it a )ield ;) you do it gets a de)ault value 002 @ut "hat happens i) you accidentally o#it a value ;t gets assigned a de)ault and "ithout "arning unless you tell gcc to "arn you !he option N-:issingN,ieldNinitiali<ers tells gcc that you "ant to speci)y every )ield "hen you initialiFe ;) you don5t a "arning "ill ,e issued
C++ Hackers Guide Ji,nde, ".. Jde,ine __attri#ute__&x' Jendi, /* ".. */ /* Nothing */
Steve Oualline
Steve Oualline
@ut since "e used __att(i#ute__**?a(n_unused_(esult++ the co#piler "ill co#plain a,out this code* result=cpp: In ,unction aint :ain&'': result=cpp:(E: warning: ignoring return $alue o, a$oid* :%_:alloc&si<e_t'') declared with attri#ute warn_unused_result
Page 1>B
C++ Hackers Guide $oid die&const char* const :sg' K // === ,unction #od%
Steve Oualline
!his tells g++ that the )unction never returns !he )unctions a#o(t and e2it have this option set Since "e5ve told g++ that die "ill never return, the co#piler "ill no longer )uss "hen co#piling the previous e&a#ple ;) "e turn on the unreacha,le code "arning 0-Wun(ea;Aa#le-;ode2 the co#piler "ill )uss i) "e try and put code a)ter the die call as it should 'or e&a#ple* Jinclude Ciostrea:H $oid die&const char* const :sg' __attri#ute__&&noreturn''; $oid die&const char* const :sg' K std::cerr CC 97I!: 9 CC :sg CC std::endl; exit&A'; L int co:pute_area&int width) int height' K int area = width * height; i, &area H= ;' return &area'; die&9I:possi#le area9'; return &;'; // 0eturn a de,ault $alue L 6hen co#piled "e get the error* gMM N-unreacha#leNcode N-all Nc die=cpp die=cpp: In ,unction aint co:pute_area&int) int'': die=cpp:(A: warning: will ne$er #e executed !his should give the progra##er "ho added the de)ault return value an idea that #ay,e his code is not going to do "hat he e&pected ;t5s al"ays good "hen the co#piler "arns you a,out strange code and as hackers "e "ant to use the co#pilers code checking to #a&i#u# advantage !he __att(i#ute__ hacks let us do Kust that
Page 1>8
Steve Oualline
Hack 33: Usin* the GCC Heap Memor! Checkin* #%nctions to Locate Errors
The Problem: 8e#ory corruption ;5# not going to go into details ;) you5re an e&perienced progra##er, you5ve gone through your share o) horri,le #e#ory pro,le#s The 'olution: .se the GG. C li,rary 0gli,c2 #e#ory checking )unctions to help locate pro,le#s !o turn on the #e#ory checking )unctions you need to put the )ollo"ing code in your progra#* Jinclude C:chec8=hH // ==== int :ain&' K :chec8_pedantic&N2
';
!he mem;Ae;5_pedanti; call #ust occur ,e)ore any allocations are done in order to turn on #e#ory checking !he argu#ent is a pointer to a )unction "hich is called "hen an error is detected ;) this para#eter is %4BB then the a de)ault )unction is used !his )unction prints an error and a,orts the progra# !he mem;Ae;5_pedanti; )unction causes the #e#ory allocation )unctions to put sentential at the start and end o) each allocated ,lock :ver ti#e you call mallo;, f(ee, or other #e#ory allocation )unction all these sentential "ill ,e checked 6hen a pro,le# is detected the progra# "ill a,ort 'or e&a#ple* Jinclude C:alloc=hH Jinclude C:chec8=hH int :ain&' K :chec8_pedantic&N2 '; char* ptr = &char*':alloc&(;'; ptrT(;U = 'S'; ,ree&ptr'; return&;'; Page 1>7 Copyright 2008, Steve Oualline
C++ Hackers Guide L 6hen run this progra# prints* :e:or% clo##ered past end o, allocated #loc8
Steve Oualline
!he m;Ae;5_pedanti; per)or#s a consistency check every ti#e #e#ory is allocated or )reed :very #e#ory ,lock is checked %s a result your progra# "ill run slo"er than nor#al !here is a )aster #e#ory check )unction, m;Ae;5 ;t turns on pointer checking only )or the pointer ,eing allocated, reallocated, or )reed (ou can )orce the syste# to check all the #e#ory pointers ,y calling
m;Ae;5_;Ae;5_all
% single pointer can ,e checked ,y the mp(o#e )unction %l#ost all o) these )unctions are docu#ented in the gli,c docu#entation 0.se the co##and in)o gli,c on #ost $inu& distri,utions 2 !he one e&ception is m;Ae;5_pedanti; ;t5s not #entioned in the docu#entation at all Ho"ever it is #entioned in the header )ile 0#check h2 So another lesson "e can learn )ro# this hack is to al"ays take a look at the header )iles to see i) "e can )ind hidden treasure
Page 1?0
C++ Hackers Guide char* dataT(;U; ,or &int i = ;; i C (;; MMi' K dataTiU = &char*':alloc&(;'; L ,or &int i = (; i C ]; MMi' K ,ree&dataTiU'; L :untrace&'; return &;'; L !his progra# is run "ith the co##and* ^ e2po(t 9:BB$._T,:.-Cmt(a;e!log ^ !Dlea5
Steve Oualline
!he result is a )ile giving us a history o) our heap allocations and )rees*
= Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z = 6tart lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;DcU lea8:T;xA;]#;aEU lea8:T;xA;]#;aEU lea8:T;xA;]#;aEU lea8:T;xA;]#;aEU lea8:T;xA;]#;aEU lea8:T;xA;]#;aEU lea8:T;xA;]#;aEU lea8:T;xA;]#;aEU !nd M M M M M M M M M M N N N N N N N N ;xA;##?#; ;xA;##?c; ;xA;##?d; ;xA;##?e; ;xA;##?,; ;xA;##B;; ;xA;##B(; ;xA;##B*; ;xA;##B?; ;xA;##BB; ;xA;##?c; ;xA;##?d; ;xA;##?e; ;xA;##?,; ;xA;##B;; ;xA;##B(; ;xA;##B*; ;xA;##B?; ;xa ;xa ;xa ;xa ;xa ;xa ;xa ;xa ;xa ;xa
Go" all "e have to do is to #atch up the mallo; calls 0denoted ,y the + lines2 and the f(ee calls 0denoted ,y the Q lines2 %ny mallo; "ithout a #atching f(ee is a #e#ory leak 'ortunately "e don5t have to hand #atch !he progra# #trace 0distri,uted "ith gli,c2 "ill do the "ork )or you %ll you have to do is )eed it the na#e o) your e&ecuta,le and log )ile* ^ mt(a;e lea5 mt(a;e!log Pe:or% not ,reed: Page 1?1 Copyright 2008, Steve Oualline
C++ Hackers Guide NNNNNNNNNNNNNNNNN Address 6i<e ;x;A;##?#; ;xa ;x;A;##BB; ;xa .aller at /hac8/lea8=cpp:(; at /hac8/lea8=cpp:(;
Steve Oualline
!here is one li#itation on the mt(a;e )unction ;t doesn5t "ork "ell )or ne. and delete 0(ou get a ,eauti)ul trace sho"ing every mallo; and f(ee ,eing generated ,y the standard C++ li,rary 2 So ,e a"are o) it5s li#itations !he #e#ory tracking and consistency checking )unctions are not the only #e#ory de,ugging )acilities ,uilt into the gli,c li,rary !here are #any "ays to hook up diagnostic code "ith the #e#ory )unctions (ou can read the docu#entation )or details Ho"ever the ones presented in the last )e" hacks "ith )ind #ost o) the co##on errors you are likely to )ind
#a;5t(a;e to get a call stack so you kno" "here you ca#e )ro#
'irst "e need to tell m;Ae;5_pedanti; that "e "ant to handle the error ourselves* :chec8_pedantic&#ad_:e:'; Go" "hen a #e#ory pro,le# is )ound, the #ad_mem )unction "ill ,e called O) course "e need to de)ine the )unction* static $oid #ad_:e:&enu: :chec8_status status' !he #a;5t(a;e )unction returns the call stack as an array o) pointers ;n order to use this )unction "e #ust )irst allocate an array to hold this data then call the )unction* $oid* #u,,erTPAS_+0A.!U; int stac8_si<e = #ac8trace&#u,,er) si<eo,&#u,,er'/si<eo,&#u,,erT;U'';
Page 1?2
Steve Oualline
!his gives us a set o) pointers, "hich is not use)ul "hen it co#es to )inding out "here "e are ;t "ould ,e nice to turn this list into so#ething printa,le "ith sy#,ols 'ortunately there5s a )unction to do that called #a;5t(a;e_s>m#ols ;t returns a array o) character pointers containing hu#an reada,le 0#ostly2 version o) our pointers "ith so#e sy#,olic in)or#ation char** stac8_s%: = #ac8trace_s%:#ols& #u,,er) stac8_si<e'; Go" all "e have to do is print the results* std::cout CC 96tac8 trace 9 CC std::endl; ,or &int i = ;; i C stac8_si<e; MMi' K std::cout CC stac8_s%:TiU CC std::endl; L !here5s one #ore thing "e have to do and that is a,ort the progra# 06ith #e#ory corrupt there5s not a "hole lot "e can do at this point 2 So the last line o) our )unction is* a#ort&'; later !he a#o(t call "as chosen ,ecause it creates a core du#p "e can analyFe % typical run o) this progra# produces the results* 6tac8 trace trace T;xA;]#BFAU /li#/tls/li#c=so=E T;xB;(]*A,?U trace&__li#c_,reeM;x(D' T;xA;BeA(DU trace T;xA;]#F(;U trace T;xA;]#F*(U trace T;xA;]#F*,U trace T;xA;]#FE?U trace&__li#c_start_:ainM;x(Bc' T;xA;BcAdcU trace&__gxx_personalit%_$;M;xF(' T;xA;BcD;(U A#orted &core du:ped' .n)ortunately the #a;5t(a;e_s>m#ols call can5t see# to )ind the sy#,ols in our progra# 06e co#piled "ith the de,ug option so they should sho" up 2 !here are nu#,er o) "ays around this pro,le# !he si#plest is to run the de,ugger on the e&ecuta,le and the core )ile and use it to display the stack trace !his gives us the a,ility not only to look at the stack trace, ,ut also the source code and the value o) the varia,les at the ti#e o) the core du#p Page 1?4 Copyright 2008, Steve Oualline
C++ Hackers Guide ^ gd# t(a;e ;o(e!E1FG@ "N2 gd# E=?N?=(=(;*:d8 &Pandra8elinux' J === usual startup chatter === .ore was generated #% a=/trace'= 3rogra: ter:inated with signal E) A#orted=
Steve Oualline
J; ;x,,,,eB(; in __ &' &gd#' ?Ae(e J; ;x,,,,eB(; in __ &' J( ;x#,,,,;Ac in __ &' J* ;x;;;;;;;E in __ &' J? ;x;;;;DcdF in __ &' JB ;x;A;A((Ae in raise &sig=E' at ==linux/raise=c:ED JF ;x;A;FDcaD in a#ort &' at a#ort=c:AA JE ;x;A;]#BeF in #ad_:e: &status=P.I!.4_+AI ' at trace=cpp:*A JD ;xB;(]*A,? in :chec8_chec8_all &' ,ro: /li#/tls/li#c=so=E JA ;x;A;BeA(D in __li#c_,ree &:e:=;xE' at :alloc=c:?F;F J] ;x;A;]#F(; in :e:_pro#le: &' at trace=cpp:?E J(; ;x;A;]#F*( in do_part( &' at trace=cpp:B; J(( ;x;A;]#F*, in do_all &' at trace=cpp:B? J(* ;x;A;]#FE? in :ain &' at trace=cpp:B] &gd#' Go" "e can use the nor#al gd, co##ands to e&a#ine the progra# 'or e&a#ple, let5s take a look at the )unction "here the error "as discovered &gd#' list t(a;e!;pp:EH ?( $oid :e:_pro#le:&' ?* K ?? char* ptr = &char*':alloc&(;'; ?B ?F ptrT(;U = 'S'; ?E ,ree&ptr'; ?D L ?A ?] $oid do_part(&' K B; :e:_pro#le:&'; &gd#' ;n this case the error is ,lindingly o,vious and "e re=uire no )urther investigation ;n the real "orld, things #ight no ,e so si#ple and "e #ight have to spend #ore than )ive seconds to )ind the pro,le# @ut at least "e have to tools in place to detect the pro,le# early and analyFe "hat the progra# is doing Page 1?> Copyright 2008, Steve Oualline
Steve Oualline
%nother "ay o) )inding out "here things are in the progra# is the addr2line co##and 0part o) the gli,c package2 ;t translates an address into a line nu#,er in the progra# 'or e&a#ple* ^ add(<line -. -f -e t(a;e 7287F#G17 :e:_pro#le:&' /ho:e/sdo/hac8/trace=cpp:?E !he -. )lag tells addr2line to de#angle C++ sy#,ols !he -f option causes the )unction na#e as "ell as the line to ,e listed !he progra# )ile is speci)ied "ith the -e option and )inally "e have the address to ,e decoded !his )unction is use)ul "hen it5s i#practical to use gd, )or e&a#ple "hen pro,le#s happen in the )ield and the custo#er doesn5t "ant to send you a ,ig core )ile, ,ut is "illing to send you the ,acktrace output Hackers kno" that there5s #ore than one "ay to solve a pro,le# So#eti#es "e have to use the all in order to )ind the one "hat "orks, ,ut )i&ing things in a poor "orking environ#ent, "ith ,ad tools, inco#plete in)or#ation, and lots o) pressure is so#ething hackers do every day
Page 1??
Steve Oualline
Page 1?A
Steve Oualline
(ou start ,y creating a de,ug h )ile that contains the varia,le declarations %ny progra# "hich uses the de,ug #odule should include the header )ile using the state#ent* // Nor:al progra: ,ile such as :ain=cpp // === Jinclude de#ug=h !he #odule de,ug cpp ho"ever uses a clever preCprocessor trick* // 5ile de#ug=cpp // === Jde,ine extern /* */ Jinclude de#ug=h Junde, extern // NN 7/ N/+ 30/"0AP line* extern int de#ug_le$el; ,eco#es* /* */ int de#ug_le$el; thus you5ve #ade one )ile do dou,le duty saving a lot o) typing !here are a )e" #aKor pro,le#s "ith this code 'irst you5ve rede)ined a standard C++ key"ord Go" "hen so#eone looks at a )ile they #ust decide i) the e4tern key"ord really #eans e4tern or does it #ean so#ething else C++ is ,ad enough "hen co#ing to you unedited 8aking key"ords #ean one thing at one point in the progra# and another thing later on #akes the progra# ten ti#es harder to de,ug Go" suppose an unsuspecting progra##er co#es across the de,ug h )ile and decided that he "ants to add a )unction to it "hich uses ;1O strea#s 'or e&a#ple* extern $oid set_output_,ile&std::ostrea:> out_,ile'; Our de,ug h )ile no" looks like* // de#ug=h &inco:plete' extern int de#ug_le$el; extern $oid set_output_,ile&std::ostrea:> out_,ile'; I4! +II6 RRR NN
!he &define state#ent #ake the e4tern key"ord disappear So no" the
Page 1?B
Steve Oualline
@ecause "e are good progra##ers "e "ant to )ollo" the rules that every header )ile should ,ring any header )ile that it needs to do its "ork ;n this case "e re)erence std::ostrea: so "e need the )strea# header )ile* // de#ug=h Jinclude C,strea:H extern int de#ug_le$el; extern $oid set_output_,ile&std::ostrea:> out_,ile'; Guess "hat %ll the e4tern declarations in )strea# have ,een edited and their e4tern re#oved !he progra# is no" ,roken So this hack prevents the progra##er )ro# )ollo"ing good coding guidelines and #aking a header )ile sel) su))icient ;t gets "orse % good progra##er "ould look at de,ug h and see that Jinclude C,strea:H is #issing O) course ,eing a good progra##er he "ants to #ake things right so he adds this line 0Got kno"ing o) course that the de,ug cpp contains the e4tern antiChack 2 Go" "hen this occurs the good progra##er ,y )ollo"ing good progra##ing practices had Kust ,roken the progra# in strange and #ysterious "ays Suddenly "hen he links in the de,ug #odule he gets duplicate de)ined sy#,ols )or thing in the )strea# #odule % close inspection o) the source code "ill not )ind the progra# !he )strea# header )ile is a syste# )ile ;t5s supposed to ,e correct @esides i) there is a pro,le# in it, the pro,le# "ill sho" up in lots o) progra#s So it5s /o,vious3 that the pro,le# is not )strea# @ut it is, sort o) @ecause the &define rede)ined the C++ language itsel), )strea# has ,een re"ritten and no" contains errors
This anti2hack breaks .orking code in a .ay that is difficult to locate6 *o not use it6
!here are a nu#,er o) other pro,le#s "ith this hack* it doesn5t allo" you to locate varia,le de)initions near the code that uses the#, it doesn5t let you initialiFe glo,al varia,les, and it greatly li#its "hat you can put in a header )ile @ut there are #inor "hen co#pared to the da#age it does ,ecause it rede)ines the C++ language
Steve Oualline
The ,nti2Hack: .se , 0co##a2 to Koin state#ents 'or e&a#ple, instead o) "riting* i, &,lag' K do_part_a&'; a_done = true; L you can do the sa#e thing "ithout the curly ,races* i, &,lag' do_part_a&') a_done = true; !his saves us t"o lines and gets rid o) t"o character 0the curly ,races2 (ou can get even #ore creative "ith for loops* ,or &cur_ptr = ,irst) count = ;; cur_ptr R= N2 cur_ptr = cur_ptrNHnext) MMcount'; ;
!he for loop "e5ve Kust de)ined counts the nu#,er o) ite#s in a linked list and through creative use o) the , 0co##a2 operator "e5ve eli#inated any code ,e)ore the for and inside the ,ody o) the for %s you can see the , 0co##a2 operator is a very po"er)ul tool )or #aking your code very co#pact @ut "hy "ould you ever "ant to do such a thingS Co#pact code #ay have ,een use)ul in the )irst days o) co#puting "hen storage cost several dollars a ,yte, ,ut today you can pick up a 1288 .S@ !hu#, drive at a convenience store 8aking the code #ore co#pact o,scures the logic and #ake the progra# #ore di))icult to read !hus such code is #ore prone to errors and the errors are #ore di))icult to )ind "hen they occur 6hen you use this hack you do not sho" ho" clever a progra##er you are :&perienced hackers already kno" a,out this trick !hey are Kust #ature enough not to use it
Steve Oualline
!he logic o) this code is si#ple and easy to understand Q and e&tre#ely #isleading Luestion* ;s the )unction do_special_stu,, e&ecuted "hen na:e is a 8e%_na:e or nonCkey peopleS -e#e#,er st(;mp returns 0 "hen the strings are e=ual So you5re only special i) you are not the key person !he code is #isleading ,ecause #ost si#ilar )unctions "ill return a true 1 )alse value, the true ,eing the positive case ;n other "ords a i) st(;mp )ollo"ed the rules, it "ould return true o) e=ual and )alse )or not e=ual !he )ollo"ing code is O<* i, &strings_are_sa:e&na:e) 8e%_na:e'' K do_8e%_stu,,&'; L ;n this case the logic o) the progra# and the inititation o) the progra##er reading the code "ill #atch and con)usion is avoided @ut "ith i, &strc:p&na:e) 8e%_na:e'' K the logic o) the co#puter clash "ith "hat anyone reading the code e&pects and you get con)usion One o) the goals o) a good hacker should ,e clarity %)ter all ho" can you sho" the "orld ho" good a hacker you are i) no one understands you "ork !he strcmp code can ,e ,etter "ritten as* // strc:p return $alue ,or eYual strings= static const int 6+0.P3_6AP! = ;; // .hec8 ,or a$erage &nonN8e%' users and process // their special reYuests= i, &strc:p&na:e) 8e%_na:e' R= 6+0.P3_6AP!' K do_special_stu,,&'; L 6hat #akes this code goodS ;t is easy to see )ro# the state#ent* i, &strc:p&na:e) 8e%_na:e' R= 6+0.P3_6AP!' K that the strings are not the sa#e @ut Kust to #ake sure people reading this code understand "hat is going a co##ent has ,een added telling the reader in :nglish "hat is going on 17
17 !he co##ent could ,e #ore precise and e&plicit e&cept this is a #ade up e&a#ple and ; le)t a great deal o) design to the i#agination
Page 1A0
Steve Oualline
Page 1A1
C++ Hackers Guide // 7on't code li8e this while &ch = getch&' R= !/5' K // === do so:ething L
Steve Oualline
!here are several things "rong "ith this code !he )irst is that it that you have to ,e care)ul can #ake sure that the varia,le ;A is not a char varia,le ;t #ust ,e an int )or the co#parison to "ork !he second pro,le# is that this code does #ultiple operations in a single state#ent %s a result the code is con)using and co#pact ;t is #uch ,etter to have code ver,ose and clear than con)using and co#pact 'inally the line* while &ch = getch&' R= !/5' K is con)using 9o you kno" i) the assign#ent operator 0C2 has higher precedence than not e=ual 0IC2S 'or e&a#ple, "hich o) these t"o state#ent is the e=uivalent o) our .hile loop* while &&ch = getch&'' R= !/5' K while &ch = &getch&' R= !/5'' K !his is one e&a#ple "here Hack 17 co#es in handy !his is a co##on, co#pact "ay o) "riting a .hile loop @ut Kust ,ecause it5s co##on does not #ean it5s good % #ore ver,ose, and easier to understand "ay o) doing the sa#e thing is* // 3lease code li8e this while &true' K int ch = getch&'; i, &ch == !/5' #rea8; // == do so:ething L Go" there are people "ho "ill tell you that this hack is use)ul !hey point out that is is very co##on and ,ecause it5s co##on people recogniFe and understand it %nd ,ecause it5s so co##on and understanda,le people "rite it in ne" code #aking it #ore co##on and )orcing #ore people to recogniFe it and understand it
Page 1A2
Steve Oualline
@ut ulti#ately it5s sloppy pattern and leads to other sloppy coding patterns 'or that reason it should ,e avoided
J$,_-:.H_IT-9 #acro 'or readers o) this ,ook the #istake is so#e"hat easy
to spot ,ecause all you have to do to )ind the #acro de)inition is to look ,ack to the previous code e&a#ple ;n real li)e things are #uch "orse !he #acro de)inition is usually hidden in a header )ile and you have to go hunting )or it ;n general it5s ,etter to "rite code "ho5s synta& is visi,le and standard !hat let5s the people "ho co#e a)ter you understand your "ork so that they can i#prove and enhance it
Page 1A4
Steve Oualline
The ,nti2Hack: .se 6define to de)ine a set o) #acros that allo" you to #ake C code look like %$OG$CA8 Here5s a s#all sa#ple* Jde,ine 1!"IN K Jde,ine !N7 L Jde,ine Jde,ine Jde,ine Jde,ine I5 +I!N ! 6! !N7I5 i, & ' K L else K L
!he code looks like* -II ! &s%ste:_read%&'' 1!"IN int success = process_c:d&'; I5 success +I!N good&'; ! 6! #ad&'; !N7I5 !N7 !his #akes things si#ple and easy to understand i) you5re an %$GO$CA8 progra##er, it #akes things ne&t to i#possi,le i) you5re a C progra##er 8ost progra##ers "hen )aced "ith this sort o) code, curse, then use the preCprocessor to re#ove the #acros and get ,ack to the underlying C code !his hack is o) historical interest ,ecause the original @orne shell "as "ritten this "ay 'ortunately it "as =uickly replaced ,y a C version #uch to the relie) o) all the people "ho had to #aintain this progra#
C++ Hackers Guide Here5s a typical call to our d(a?_#o2 )unction* draw_#ox&1/S_-I7+I) F) 1/S_I!I"I+) ?) N2 ;n this case the N2 ';
Steve Oualline
!his concept can ,e e&panded even )urther Suppose this ,o& contains a list o) "ords Go" "e can do the )ollo"ing* draw_#ox&1/S_-I7+I) F) 1/S_-/076) alpha) #eta) N2 1/S_I!I"I+) ?) N2 '; )
So the "ord list 01/S_-/0762 no" takes a varia,le list o) "ords as it5s para#eter So "e have varia,le para#eter lists in varia,le para#eter lists !his is e&tre#ely cleverN !his is also e&tre#ely dangerous and stupid 'irst o) all this co#pletely de)eats the C++ type checking #echanis# ;n this e&a#ple, 1/S_-I7+I is supposed to ,e )ollo"ed ,y an int @ut "hat i) "e )ollo" it "ith a string draw_#ox&1/S_-I7+I) large) // ==== !he co#piler has no "ay o) kno"ing that the "rong type has ,een supplied !he runti#e has no "ay o) telling a pointer )ro# an integer On #ost syste#s a pointer looks like a very large pointer So the result o) this code is a very large ,o& and a very con)used progra##er @ut that5s not the "orst 6hat happens i) you leave out a N2 S ;) you leave out the ter#inating N2 , the )unction has no "ay o) telling "here the end o) the argu#ent list is 6hat "ill happen is that it "ill go through the argu#ents and look )or a N2 to stop on Got )inding one it "ill continue on using "hatever is store on the stack are argu#ents, until ,y accident it )inds a N2 Or crashes, or so#ething else evil happens ;n any case the result is une&pected and di))icult to diagnose @ecause this syste# de)eats so #any o) the C++ sa)ety checks it should ,e avoided !here are lots o) other "ays o) passing in large nu#,er o) argu#ents "hich provide ,oth )le&i,ility and sa)ety 0'or e&a#ple see Hack > 2 .se one the# instead
Page 1A?
Steve Oualline
Page 1AA
Steve Oualline
8icroso)t Gotation 0also kno"n as Hungarian Gotation202 is a na#ing syste# "here each varia,le is pre)i&ed "ith type in)or#ation 'or e&a#ple integers ,egin "ith /i3 and )loating point varia,les ,egin "ith /)3 Short integers ,egin /si3 as in si6i<e .nless the short integer is a handle to so#ething, then the /h3 notation kicks in 'or e&a#ple, h,.urrent5ont is a )ont handle O) course so#e people ,elieve that /h3 is too cryptic so they use /hndl3 as hndl.urrent5ont, ,ut this can lead to con)usion as the sa#e pre)i& can ,e used )or )ont handles, "indo" handles, and all the other #any other handles you have to deal "ith in 8icroso)t "indo"s !here are a nu#,er o) pro,le#s "ith this syste# !he )irst is that the "hole idea o) having a co#piler and a high level language is to hide the details o) the i#ple#entation )ro# you Putting this ,ar) on the ,eginning o) each varia,le gives you in)or#ation that you really don5t care a,out !he co#piler needs to kno" detailed type in)or#ation on every varia,le, you do not !he second pro,le# is that there is no standard list o) pre)i& characters 8any people invent their o"n leaving you to guess "hat the di))erence ,et"een ps<Na:e and s<Na:e is !he ans"er is that the )irst is a pointer to a string ending in a Fero character 0i#ple#ented ,y char72 and the second is a string ending in a Fero character 0i#ple#ented ,y char72 ;n other "ords, there is no di))erence 'inally there is the pro,le# o) )le&i,ility and progra# updates Suppose you have i#ple#ented an address ,ook and address is stored in a structure 0stAddress2 (ou i#prove the progra# and replace the structure "ith a class 0cAddress2 %re you going to go through your entire progra# and update the pre)i& o) every address varia,le in itS ;) you do it5s a lot o) "ork 0Got good 2 ;) you don5t you no" have varia,les "hich use an incorrect pre)i& 0Eery not good 2 !his is a loose and loose "orse situation (ou should "rite varia,le na#es using as clear as :nglish 0or "hatever your native language is2 as possi,le $eave type in)or#ation to the co#piler 9on5t #ess up good "ords "ith rando# ,ar) Progra#s are o,scure enough "ithout using notation syste#s "hich o,scure the# #ore "hile adding no value to the progra#
20 !he Hungarians are nice people and should ,e associated "ith such a ,ad hack So that5s "hy the ter# 8icroso)t Gotation is used here even though the ter# Hungarian Gotation is #ore co##only used
Page 1AB
Steve Oualline
Over the years C and C++ progra##ers have devised #any "ays o) #aking their "riting clearer %s a result progra# are #uch #ore reada,le than ever ,e)ore ;5ve o)ten "ondered i) the lessons learned ,y progra##ing could ,e applied to :nglish as "ell !ake 8icroso)t notation 0aka Hungarian notation2 )or e&a#ple ;t puts a pre)i& on each varia,le na#e telling us "hat the type o) the varia,le 6ouldn5t :nglish ,e #uch clearer i) "e identi)ied each ver, "ith UvU, each noun "ith UnU and so on p%)ter av%ll a8any n:nglish n6ords vCan vHave a8ore c!han nOne n8eaning p'or n:&a#ple U#allU v;s pr@oth a% nEer, c%nd a% nGoun p6ith pnOur aGe" nGotation p(ou vCan v6rite nSo#ething a$ike, Ua!here v6as aSuch a% nCro"d p%t ar!he n8all a!hat pn6e v6ere v8alledU c%nd nPeople vCan a:asily v.nderstand p(ou
Page 1A8
Steve Oualline
Page 1A7
C++ Hackers Guide 6e had a deal "ith the shoe#aker "ho "as ,uying the #achine He "ould supply us "ith ra" #aterial )or testing and "e "ould give hi# ,ack any pieces cut out during the test process so he could #ake tennis shoes out o) the# Q or so "e thought
Steve Oualline
;n order to get consistent ti#ing results "e did all our ,ench#arking using a single siFe Q 7 right So )or a,out ?CB #onths "e did nothing ,ut cut out a ,atch o) 7 rights, tune the #achine, and ship the cut pieces to the shoe#aker !his "as a very large co#pany "ith #any people "ho turn out hundreds o) thousands o) sho"s each year %)ter )inally getting the #achine tuned and "orking really "ell, "e started the process o) ,reaking it do"n )or ,o&ing and shipping to the custo#er ;t "as then that "e got a call )ro# the )actory )ore#an /%re you the people "ho keep shipping us these 7 rightsS3 6e told hi# "e "ere /'inally ; tracked you people do"n Purchasing had no idea "ho you "ere ,ecause "e never ordered any 7 rights )ro# anyone ; never thought to look at our capitol e=uip#ent ac=uisition group until no" 3 /;s there so#e pro,le# "ith our cut piecesS3 6e "ere a little "orried at this point /Got e&actly, ,ut do you realiFe that you sent us 10,000 nineCrights and no le)tsN322
Page 1B0
Steve Oualline
$ight 1 "as supposed to ,e /Oil Pressure $o"3 and it "as /-a# )ailure3 $ight 2 "as supposed to ,e /6ater Supply 'ailure3 and it "as /Positioner :rror 3 $ight 4, /9C Po"er 'ailure3 turned out to ,e /Co#pressor 'ailure3 So ; "rote up a nice docu#ent descri,ing "here ho" the syste# "as really "ired and ; handed this to the hard"are guide telling hi# /6oody, the lights are all #i&ed up 3 ; handed hi# the paper, /Here5s ho" they are currently "ired up 3 He took the paper )ro# #y hand and "ent straight to the copy #achine and #ade a copy He then handed #e the copy 0not the original2 and said, /Here5s the ne" speci)ication 3 The Hack: !est early, test o)ten !he )irst thing you should do "hen )aced "ith any ne" piece o) hard"are is to create a short diagnostic progra# that tests out it5s ,asic )unctionality ;t is this progra# "hich lets you discover things like*
Co##ands that don5t )unction as docu#ented @yte order pro,le#s 0"hich o) course are not docu#ented2
9ocu#ent that contains nonCstandard ,it order notation 0;5ve actually read one hard"are #anual that put the least signi)ication ,it on the le)t and the #ost signi)icant on the right 2
Other o#issions, errors, a#,iguities, and pro,le#s "ith the docu#entation
9ealing "ith ne" hard"are )or the )irst ti#e is a di))icult and challenging operation 'ar too #any hard"are people don5t speak so)t"are and don5t kno" ho" to "rite decent docu#entation 0% lot o) so)t"are people are Kust as ,ad "hen it co#es to "riting things do"n 2 @y testing early you can )ind out ho" the hard"are really "orks instead o) ho" it5s supposed to "ork !hat "ay you can "rite a progra# that really does the Ko, instead o) one that supposed to do the Ko,
Hack 113: Use 'orta0le )!pes Which Speci,! E&actl! Ho" Wide :o%r Inte*ers 7re
The Problem: !he C++ does not de)ine ho" #any ,its are in the int type 0Or any other type )or that #atter 2 ;n e#,edded syste#s "e need to kno" the e&act nu#,er o) ,its in order to talk to the hard"are
Page 1B1
Steve Oualline
The Hack: 9e)ine porta,le types or use the porta,le types already de)ined )or you !he header )ile Ns>sDt>pes!AO contains a set o) type de)initions provide e&act de)initions )or integer values !he include*
int8_t u_int8_t
int1H_t u_int1H_t
intE<_t u_intE<_t
intH=_t u_intH=_t
@y using these types you are guaranteed that the integers you de)ine have the e&act nu#,er o) ,its you e&pect ;) your syste# doesn5t have these types in a header )ile so#e"here, then de)ine your o"n 0%nd o) course veri)y the# ,e)ore you pu,lish the# 2
//T;U Nu:#er o, entries //T*U 1loc8s a$aila#le //TBU 1loc8s used //TEU 1loc8s re:aining_ //TAU 1ad #loc8s //T(;U ast ti:e updated //T(BU .hec8su: part ( //T(EU .hec8su: part * //T(AU `un8 //T*;U Version nu:#er //T**U Not used
Page 1B2
Steve Oualline
6hen #usic "as loaded into the -;O player so#e pro,le#s "ere o,served 'irst each ti#e you started to play a song, you got a short ,last o) noise )ollo"ed ,y the song Secondly i) you pressed the )ast )or"ard ,utton, the player "ould Ku#p to the ne&t song So "hat is going on hereS !his pro,le# is especially di))icult to de,ug ,ecause there5s no o))icial docu#entation on the -;O5s inter)ace and there5s a,solutely no "ay o) telling "hat5s going inside the device Ho"ever, you #ay have noticed that "e only included the header de)inition in this ,ook, so that #ay give you so#e idea !he actual pro,le# concerns the "ay that the co#piler lays out structures 6e can discover through testing "hat the real o))sets o) each )ield are !he results are slightly di))erent )ro# the ones "e hand co#puted and put in the co##ents* u_int(E_t #loc8_re:aining; u_int(E_t .ount?*41loc81ad; int?*_t +i:e ast2pdate; u_int(E_t chec8_su:(; //TEU //TAU //T(; // //T(B // 1loc8s re:aining_ 1ad #loc8s (*U ast ti:e updated (EU .hec8su: part (
So ho" co#e the t"o ,yte .ount?*41loc81ad takes up )our ,ytesS !he ans"er is that the co#piler "ants to align 42 ,it values 0+i:e ast2pdate2 on a > ,yte ,oundary !he o))set 10 is not on a > ,yte ,oundary, so the co#piler puts in a couple o) padding ,ytes to #ove the )ield to the ne&t )our ,yte ,oundary So the real structure layout is* u_int(E_t #loc8_re:aining; u_int(E_t .ount?*41loc81ad; u_char hidden_padT*U; int?* +i:e ast2pdate; u_int(E_t chec8_su:(; //TEU 1loc8s re:aining_ //TAU 1ad #loc8s //T(;U Added #% co:piler //T(; // (*U ast ti:e updated //T(B // (EU .hec8su: part (
So our ?12 ,yte structure is really ?1> ,ytes and so#e o) the )ields are in the "rong place 0So#e o) you #ight ask the =uestion /;) ;Ae;5_sum1 and ;Ae;5_sum< are in the "rong place, "hy doesn5t the -;O detect that the checksu#s are incorrect and display an error #essageS Good =uestion, ,ut as a so)t"are hacker you should kno" ,etter than to e&pect consistency, sanity, or co##on sense )ro# a hard"are designer 2 Go" that "e kno" "hat caused this pro,le# "hat can "e do to prevent things like this )ro# occurring in the )utureS Page 1B4 Copyright 2008, Steve Oualline
Steve Oualline
The Hack: Eeri)y the co#puted siFe o) structure against the actual siFe Si#ply put, our progra# needs the )ollo"ing line* assert&si<eo,&struct rio_dir_header' == F(*'; !his should ,e done )or every data structure shared ,y the so)t"are and the hard"are %s "e have seen the so)t"are5s idea o) "hat goes on in a structure can ,e di))erent )ro# the hard"are5s % possi,le cure )or this pro,le# can ,e )ound in Hack 11A
Page 1B>
Steve Oualline
struct rio_dir_header K u_int(E_t entr%_count; //T;U Nu:#er o, entries // ==== L __attri#ute__&&pac8ed''; // Iac8 B( !his is an e&a#ple o) the hacker using the )eatures provided ,y the co#piler to the )ullest ;) you are not using gcc read your co#piler5s docu#entation Chances are they have so#ething si#ilar to the packed attri,ute ;) your co#piler doesn5t support packing o) any type, you5ll have to split the long )ield +i:e ast2pdate into s#aller t"o u_int1H_t )ields that the co#piler "ill pack 6hen encountering a pro,le# like this a good hacker "ill )ind so#e "ay o) going over, under, or through road,locks put up ,y the co#piler
The Problem: % good co#piler "ill re#ove useless code ;n e#,edded progra##ing so#e code is not as useless as it appears $et5s suppose "e are dealing "ith a serial ;1O controller ;n order to clear the device "e need to unload the three character input ,u))er !he code )or this is* // -on't wor8 // +he de$ice is a :e:or% :apped I// de$ice // Initiali<e the pointer to the input register char* serial_char_in = 7!VI.!_3+0_6!0IA _IN; // === char Xun8_ch; // A Xun8 character Xun8_ch = *serial_char_in; // 0ead one useless character Xun8_ch = *serial_char_in; // .lear second useless char Xun8_ch = *serial_char_in; // +hird character gone // #u,,er now clear So "hat does this code really doS ;t assigns Xun8_ch the top character )ro# the device !his is repeated three ti#es so clear the three character ,u))er
Page 1B?
Steve Oualline
@ut the co#piler is s#art ;t looks at this code and says, /!hat )irst assign#ent is useless 6e co#pute the value o) Xun8_ch only to thro" it a"ay ; can eli#inate that line and the progra# "ill act the sa#e 3 So the opti#iFer re"rites the code to look like* char Xun8_ch; // A Xun8 character Xun8_ch = *serial_char_in; // 0ead one useless character ///////////////////////////////////////////////////////// Xun8_ch = *serial_char_in; // .lear second useless char Xun8_ch = *serial_char_in; // +hird character gone Go" it looks at the second line ;t too can ,e eli#inated !he third line can only ,e eli#inated i) Xun8_ch is not used so#e"here later in the progra# ;n this e&a#ple, it5s not so it too is eli#inated !he resulting code is very nicely opti#iFed* char Xun8_ch; // A Xun8 character Xun8_ch = *serial_char_in; // 0ead one useless character ///////////////////////////////////////////////////////// Xun8_ch = *serial_char_in; // .lear second useless char //////////////////////////////////////////////////////// Xun8_ch = *serial_char_in; // +hird character gone /////////////////////////////////////////////////// %nd since Xun8_ch is no" never used, the co#piler can #ake the varia,le disappear and save the stack space it "ould use So the opti#iFer had saved us ti#e ,y cutting out useless instructions and #e#ory ,y eli#inating a useless varia,le 6hat5s "rong "hat thatS !he ans"er is that the progra# no longer )unctions !he device is no longer getting cleared !his is one pro,le# "ith e#,edded progra##ing, the co#piler does not kno" a,out the strange side e))ects that can occur "hen dealing "ith #e#ory #apped ;1O The Hack: .se the volatile key"ord to identi)y #e#ory #apped device and other volatile data !he volatile key"ord tells C++ that a varia,le #ay ,e changed at any ti#e ,y )orces outside the control o) the nor#al progra##ing environ#ent 8ore speci)ically it tells the co#piler that opti#iFer is not allo"ed to change the nu#,er or order o) any access to this varia,le $olatile char* serial_char_in = 7!VI.!_3+0_6!0IA _IN; Go" "e "e e&ecute*
Page 1BA
Steve Oualline // 0ead one useless character // .lear second useless char // +hird character gone
the ;1O device "ill ,e accessed three ti#es and "e "ill clear the device %lert readers #ay notice that "e violated Hack 4 and didn5t use const "here "e should have Since "e don5t "hat to change the pointer, it should ,e #ade const giving us* $olatile char* const serial_char_in = 7!VI.!_3+0_6!0IA _IN; Go" "e have enough advanced key"ords in a single varia,le declaration to identi)y us as a real hacker
C++ Hackers Guide const int 7! AG_./2N+ = (;;; // int result; ,or &int i = ;; i C 7! AG_./2N+; MMi' K result = (* * ?B; L
@ut there are so#e surprises in this code 'irst o) all ho" #any ti#es is the e&ecuted* a2 Iero ti#es ,2 One ti#e c2 100 ti#es ;) you guessed /a3 you5re right Q so#eti#es @ut /,3 and /c3 are also right Q so#eti#es !he pro,le# is that the opti#iFer #ay play all sorts o) ga#es "ith this code !he opti#iFer #ay look at the code and deter#ine that all this code is "aste ti#e so it can ,e eli#inated So the loop "ill e&ecute Fero ti#es ;) (esult is used later in the code, then one trip through the loop is enough and the opti#iFer can drop the other 77 !he GG. C++ co#piler is s#art ;ts opti#iFer says /!his code looks like the useless code you5re )ind in a delay loop, so ;5ll generate the code to go through the loop 100 ti#es 3 !he second =uestion is /Ho" #any ti#es is the #ultiply doneS3 :ven "ithout the opti#iFer the ans"er to this =uestion Fero %ny #odern co#piler kno"s ho" to do constant )olding and "ill evaluate constant e&pressions at co#pile ti#e so they don5t have to ,e co#puted at run ti#e The Hacks: %ctually there are t"o hacks in play here !he )irst is to periodically look at the asse#,ly code to see "hat the co#piler is doing to you !he second is to use the volatile #odi)ier to )orce the co#piler to not opti#iFe your code $et5s take a look at "hat the GG. co#piler does "ith our original delay loop* :o$l ^]]) \eax = F: decl \eax Page 1B8 Copyright 2008, Steve Oualline
Steve Oualline
So "e have the loop part, ,ut not the #ultiple part !his "ill generate so#e delay ,ut not enough So let5s re"rite the loop using volatile varia,le !he volatile key"ord tells the co#piler that this varia,le is special and to #ake no assu#ptions a,out the saneness o) this varia,le Here5s the ne", i#proved loop* $olatile int result; $olatile int ,( = (*) ,* = ?B; ,or &int i = ;; i C (;;; MMi' K result = ,( * ,*; L Go" )ro# the asse#,ly code "e can see that the #ultiply is actually happing and our delay loop is causing a delay :o$l ^]]) \ecx :o$l ^(*) NA&\e#p' :o$l ^?B) N(*&\e#p' = F: :o$l NA&\e#p') \eax :o$l N(*&\e#p') \edx i:ull \edx) \eax decl \ecx :o$l \eax) NB&\e#p' Xns = F 'inally a good hacker "ould design a short test progra# to test the length o) this delay loop 9elay loops are e&tre#ely di))icult to get right and the processor #ight have so#e surprises in store )or you as "ell ;t should ,e pointed out that hackers avoid "riting delay loops like this as #uch as possi,le Such loops are dangerous to code, nonCporta,le, and a "aste o) CP. resources !hey should only ,e created i) there is there is no other "ay o) getting the progra# to )unction @ut no" at least i) "e5re )orced to use the#, "e can get the# right
Page 1B7
Steve Oualline
Page 180
C++ Hackers Guide // "ood e:#edded code while &(' K the_connectionNHconnect_to_ser$er&'; i, &R &the_connection=#ad&'' #rea8; log_warning& 2na#le connect= -ill retr% in \d seconds) ./NN!.+_7! AG'; sleep&./NN!.+_7! AG'; L
Steve Oualline
So "hat happens i) the server is not readyS ;n this case "e log an error 0to tell so#eone "e had a pro,le#2, then "ait a )e" seconds 0no need to pound the server2, and try again So even i) it takes a "hile )or the server to co#e up, "e "ill eventually connect to it ;) the server never co#es up, the "e never co#e up, ,ut that is not our pro,le# ;t is up to "hoever is handling the server to )igure out a "ay )or it to co#e up, and "hen it does "e5re ready So the ,asic rule is that the progra# "ill keep trying until it succeeds ;t never stops ,ecause it5s al#ost i#possi,le to start it again 0;n ,adly progra##ed syste#s, the only "ay to restart dead processes is to po"er cycle the #achine 2 @ut "hat happens i) your progra# encounters a pro,le# "here retrying is not an option 'or e&a#ple* tr% K char *#u,,er_we_:ust_ha$e = new charT1255!0_6I[!U; // ==== L catch &std::#ad_alloc e' K // __ -hat do we do now_ L !here is no "ay "e can keep retrying the ne. operation until "e get enough #e#ory %)ter all do "e e&pect the user to solve the pro,le# ,y going out, ,uying a #e#ory chip and installing it "hile our progra# keeps runningS Go, in this case "e #ust a,ort !he progra# can no longer )unction @ut in e#,edded progra##ing "e should keep things running "henever possi,le So one hack around the a,ort pro,le# is to #ake sure that i) a progra# does a,ort, "e start it right up again Page 181 Copyright 2008, Steve Oualline
Steve Oualline
So "e create a s#all e&ecutive progra# "hich #onitors our #ain progra#* while &(' K s%ste:&:ain_progra:'; log_warning&:ain_progra: stopped= sleep&6!++ !_+IP!'; L
-ill restart=';
%s hackers "e al"ays kno" that there is so#e "ay around /i#possi,le3 restrictions ;n e#,edded syste#s, "e can5t stop, and i) "e do stop, "e don5t stop )or long Go #atter "hat happens, the syste# #ust run
Steve Oualline
!he idea is that "atchdog e&pects to have so#eone tickle it every )ive #inutes ;) it doesn5t it "ill get angry and re,oot the syste# 6e are going to tickle is every thirty seconds 0!hat5s #uch less that )ive #inutes2 so "e should ,e sa)e ;) )or so#e reason the syste# gets really ,usy, so ,usy it can5t give our poor tickle process any CP. in )ive #inutes, then the progra# "ill )ail to tickle the "atchdog, the "atchdog "ill get upset and "e5ll re,oot !here are a nu#,er o) hard"are ,ased "atchdog ,oards availa,le as "ell as a so)t"are only kernel driver !hese are all docu#ented in the kernel source in the directory 1usr1src1linu&19ocu#entation1"atchdog ;t should ,e noted that this hack is a solution o) last resort ;t should only ,e used "here the choices are to let the syste# ,e per#anently hung up or reset the syste# Hope)ully the other protections you5ve got ,uilt into the syste# "ill prevent you )ro# ever having to let the "atchdog do its Ko, @ut it a good )ailsa)e against the "orst happening
Page 184
Steve Oualline
Synta& Coloring .sing Ei#5s ,uiltCin #ake syste# %uto#atic ;ndentation Source code e&ploration Eie"ing the $ogic o) $arge 'unctions $og )ile vie"ing
:ven i) you are progra##ing on 8icroso)t 6indo"s you can use Ei# %lthough progra##ing environ#ents like Eisual C++ provide you "ith an editor, the Ei# is )ar superior at editing that their internal editor ote* !his chapter assu#es that you have turned on Ei# e&tended )eatures On .G;T and $inu& syste#s this is done ,y creating a ^1 vi#rc )ile On 8icroso)t 6indo"s this is done ,y de)ault What is 9im
Ei# is a high =uality te&t editor "ho5s one Ko, is to edit te&t )ast ;t is designed )or people, like progra##ers, "ho have to edit a lot o) te&t
One o) the pro,le#s "ith Ei# is its steep learning curve !he #ain cursor #ove#ent keys are h, 3, k, and l ;) you look on a key,oard you5ll see that these keys are the /ho#e3 type positions on the right hand ;n other "ords, they are the )astest and easiest keys )or #ost people to type
Page 18>
Steve Oualline
@ut they are totally nonC#ne#onic 0'or e&a#ple, right is l 0lo"er case $2 2 $earning Ei# takes ti#e, ,ut one you do learn the# you can edit =uicker than al#ost any other editor 24
24 :#acs users "ill pro,a,ly challenge this state#ent as "ell as people "ith other )avorite editors ;) you are one o) these people you can easily skip this chapter
Page 18?
Steve Oualline
Page 18A
C++ Hackers Guide int :ain&' K int (=? do_su#&9,oo9'; MMi; return &;'; L L Q &F o, (*': parse error #e,ore aLb
Steve Oualline
'igure 8* :cnext
!he co##and :;p(e ious or :;%e2t goes to the previous error Si#ilarly, the co##and :;last goes to the last error and :;(e?ind goes to the )irst !he :;nfile goes to )irst error #essage )or the ne&t )ile 0see 'igure 72 int su#&int i' K return &i * X' L Q Q Q Q Q Q &D o, (*': aX' undeclared &,irst use in this ,unction'
Page 18B
Steve Oualline
'inally the :Aelp co##and can ,e used to get docu#entation on all the co##ands presented here
Steve Oualline
The Hack: .se Ei#5s internal indentation )unctionality to do the "ork )or !o indent a ,lock o) te&t using Ei# e&ecute the )ollo"ing co##ands* 1 Position the cursor on the )irst line to ,e indented 2 :&ecute the ' 0upper case /v32 co##and to start /E;S.%$ $;G:3 #ode 4 8ove to the last line to ,e indented using any o) the Ei# #ove#ent co##ands !he ,lock to ,e indented "ill ,e highlighted 0See 'igure 11 2 > :&ecute the Ei# co##and C to indent the highlighted te&t
Page 187
C++ Hackers Guide Start here // .ode intentionall% indented wrong int do_it&' K i, &toda%' do_toda%&'; Press E do_now&'; 8ove to do_reYuired&'; here do_,inish&'; L int :ain&' K do_it&'; return&;'; L Press C -esult* // .ode intentionall% indented wrong int do_it&' K i, &toda%' do_toda%&'; do_now&'; do_reYuired&'; do_,inish&'; L int :ain&' K do_it&'; return&;'; L
Steve Oualline
Page 170
Steve Oualline
The Hack: .se the ctags2> co##and to generate a location )ile 0called tags2 "hich Ei# can use to locate )unction de)initions (ou need to generate the tags )ile ,e)ore you start editing !his is done "ith the co##and ^ ;tags M!;pp M!A Go" "hen you are in Ei# and you "ant to go to a )unction de)inition, you can Ku#p to it ,y using the )ollo"ing co##and* :tag do_tAe_funn>_#i(d !his co##and "ill )ind the )unction even i) it is another )ile !he .T,B-] co##and Ku#ps to the tag o) the "ord that is under the cursor !his #akes it easy to e&plore a tangle o) C++ code Suppose, )or e&a#ple, that you are in the )unction write_#loc8 (ou can see that it calls write_line @ut "hat does write_line doS @y putting the cursor on the call to write_line and typing .T,B-], you Ku#p to the de)inition o) this )unction 0see 'igure 122 !he write_line )unction calls write_char (ou need to )igure out "hat it does So you position the cursor over the call to write_char and press .T,B-] Go" you are at the de)inition o) write_char 0see 'igure 142
2> 8ake sure you get the e&tended version )ro# http*11ctags source)orge net1
Page 171
C++ Hackers Guide $oid write_#loc8&char line_setTU' K int i; ,or &i = ;; i C N_ IN!6; MMi' write_line&line_setTiU'; L
Steve Oualline
$oid write_line&char lineTU' .+ K o, w int i; i, n ,or &i = ;; lineT;U R= '@;'' write_char&lineTiU'; L Q 9write_line=c9 E )
Page 172
Steve Oualline
Q :tags J +/ tag 50/P line in ,ile/text ( ( write_#loc8 ( write_#loc8=c * ( write_line F write_#loc8=c ? ( write_char F write_line=c H 3ress 0!+20N or enter co::and to continue
write_block
write_line
write_char
<.T,B-T
:<tag :tag
.T,B-T
Page 174
Steve Oualline
Hack 12.: :o% =eed to #ind the Location o, 'roced%re ,or Which :o% 8nl! no" 'art o, the =ame
The Problem: (ou Usort o) U kno" the na#e o) the procedure you "ant to )indS !his is a co##on pro,le# )or 8icroso)t 6indo"s progra##ers ,ecause o) the e&tre#ely inconsistent na#ing convention o) the procedures in the 6indo"s %P; .G;T progra##ers )are no ,etter Only the inconsistency in na#ing conversions is consistent] the only pro,le# is that .G;T likes to leave letters out o) syste# call na#es 0)or e&a#ple, creat2 The Hack: .se the :tag co##and to search )or procedures using a regular e&pression ;) a procedure na#e ,egins "ith D, the :tag co##and assu#es that the na#e is a regular e&pression ;) you "ant to )ind a procedure na#ed Uso#ething "rite so#ething,U )or e&a#ple, you can use the )ollo"ing co##and* :tag /write !his )inds all the procedures "ith the "ord "rite in their na#es and positions the cursor on the )irst one ;) you "ant to )ind all procedures that ,egin "ith read, you need to use the )ollo"ing co##and* :tag /cread ;) you are not sure "hether the procedure is 7o5ile, do_,ile, or 7o_5ile, you can use this co##and* :tag /7o5ile@Odo_,ile@O7o_5ile or :tag /T7dUo_@=T5,Uile !hese co##ands can return #ultiple #atches (ou can get a list o) the tags "ith the )ollo"ing co##and* :tselect name 'igure 1A sho"s the results o) a typical :tsele;t co##and
Page 17>
Steve Oualline
J pri 8ind tag ,ile H ( 5 . , write_char write_char=c $oid write_char&char ch' * 5 , write_#loc8 write_#loc8=c $oid write_#loc8&char line_setTU' ? 5 , write_line write_line=c $oid write_line&char lineTU' B 5 , write_raw write_raw=c $oid write_raw&char ch' !nter nr o, choice &C.0H to a#ort':
!he last line o) the :tsele;t co##and gives you a pro#pt that ena,les you to enter the nu#,er o) the tag you "ant Or you can Kust press :nter 0N.,O in Ei# ter#inology2 to leave things alone !he g] co##and does a :tsele;t on the identi)ier under the cursor !he :tjump co##and "orks Kust like the :tsele;t co##and, e&cept i) the selection results in only one ite#, it is auto#atically selected !he g.T,B-] co##and does a :tjump on the "ord under the cursor % nu#,er o) other related co##ands relate to this tag selection set, including the )ollo"ing*
:count tne2t :count tp(e ious :count t%e2t :count t(e?ind :count tlast
Go to the ne&t tag Go to the previous tag Go to the ne&t tag Go to the )irst tag Go to the last tag
'igure 1B sho"s ho" to use these co##ands to navigate ,et"een #atching tags o) a :tag or :tsele;t co##and Page 17? Copyright 2008, Steve Oualline
Steve Oualline
write_char
!he : img(ep co##and acts #uch like :ma5e ;t runs the e&ternal progra# grep and captures the output !o )ind all occurrences o) the varia,le groundJpoint, )or e&a#ple, you use this co##and*
Page 17A
C++ Hackers Guide MMi; return &;'; L L :ain=cpp:F: int i=?; :ain=cpp:D: MMi; su#=cpp:(:int su#&int i' su#=cpp:?: return &i * X' &( o, B': : int i=?; 3ress 0!+20N or enter co::and to continue
Steve Oualline
Steve Oualline
Press ' to start visual line #ode !he line "ill ,e highlighted i, &,lag' K start_o,_long_code&'; // ()A?B :ore lines o, code end_o,_long_code&'; L else K return &error_code'; L Go to the end o) the long code (ou can do several "ays* 1 8ove the cursor using the nor#al cursor #ove#ent co##ands such as j 0do"n2 or D 0search2 2 Go up to the curly ,racket and press R 0)ind #atching ,racket2, then #ove up a line 4 :nter the operator pending co##and i& to select the te&t inside the
KL
6hen you )inish #oving the cursor the lines inside the KL "ill ,e highlighted i, &,lag' K start_o,_long_code&'; // ()A?B :ore lines o, code end_o,_long_code&'; L else K return &error_code'; L Go" enter the co##and F) to /)old3 the highlighted te&t !he 1,84A lines o) code are no" replaced ,y a single line telling you that a )old has ,een placed here i, &,lag' K +--- 1836 lines: start_of_long_code( ! ------------------+ L else K return &error_code'; L !he editor no"s gives you an idea "hat the logic o) the )unction looks like ;) you "ant to see the te&t again, position the cursor on the )old line and type )o Page 178 Copyright 2008, Steve Oualline
Steve Oualline
!here is a lot going on here, so you #ay "ish to ,ro"se the help te&t !o get help on the co##ands docu#ented e&ecute the )ollo"ing co##ands*
Help Command
Topic
Eisual 8ode 0the highlighting2 8atch OP 0and other things2
Select inner ,races 0te&t ,et"een OP2 Create )old -e#ove 0open2 )old
Page 177
Steve Oualline
!here are lots o) "ays o) #anipulating te&t in Ei# 'ar too #any to list
!he co#,ination o) e&tensive logs and a good te&t editor #akes it easy to locate and vie" the in)or#ation "e "ant !his nonCstandard use o) a te&t editor is one "ay a good hacker can think /out o) the ,o&3 and #ake )ull use o) the tools availa,le to hi#
Page 200
Steve Oualline
Page 201
Steve Oualline
The Hack: !he varia,le can ,e toggled ,et"een the t"o values "ith one si#ple su,traction state#ent* ,lag = ? V ,lag; (ou can no" take a )e" seconds to veri)y the correctness o) this state#ent !his code )unctions ho"ever it is inco#plete ;) you #ust include clever code in your progra# like this, please please include co##ents telling the people that co#e a)ter you "hat you5ve done // +his cle$er piece o, code ,lips the ,lag $aria#le // #etween the $alues o, ( and *= ,lag = ? V ,lag; !his is al#ost the per)ect hack ;t is clever, it is s#all, it is e&tre#ely )ast, and it is clear 0a)ter the addition o) the co##ent2 Go" i) "e could Kust )ind so#e progra# "e could use it in
C++ Hackers Guide like* int :ain&' K int a = (; int # = *; print&a)#'; swap&a)#'; print&a)#'; return&;'; L
Steve Oualline
$et5s take a look at "hat the opti#iFer did )or us !he )irst test code looks
-unning this through the co#piler and taking a look at the asse#,ly code generated "e can see that the co#piler re"rote our #ain )unction* print&a)#'; print&#)a'; !he swap call "as eli#inated co#pletely So not only did the co#piler eli#inate the te#porary, it also eli#inated all the code as "ell (ou can5t get #ore opti#iFed that that ;) "e change our test to )orce the actual s"apping o) the varia,les "e get the )ollo"ing code* :o$ :o$ :o$ :o$ reg() a reg*) # a) reg* #) reg(
Go" registers don5t count as te#porary varia,les 0at least i) ;5# doing the counting2 so again "e have a case "here "e are s"apping the varia,les "ithout a te#porary !his =uestion lets us illustrate several attri,utes o) a true hacker !he )irst is a "illingness to think outside the ,o& %nyone can look up the standard ans"er on the ;nternet @ut only a good hacker "ill ask the =uestion /Hey, "hat "ill happen i) 3 and then per)or# a ,unch o) e&peri#ents ans"ering that =uestion ;) the hacker is really good you )ind yoursel) "ith an ans"er that is surprising and #uch ,etter than the /standard3 ans"er
Page 204
Steve Oualline
C++ Hackers Guide L L // 0e$erse the words in a string // &-ithout a te:porar%' $oid re$erse&char* const str' K // 0e$erse the entire string re$_chars&str) str M strlen&str'N('; // 3ointer to the ,irst character o, a word // to re$erse char* ,irst_ptr = str;
Steve Oualline
// 4eep looping until we run out o, string while &*,irst_ptr R= '@;'' K // Po$e up to the ,irst letter o, the word while &R isalpha&*,irst_ptr'' K i, &*,irst_ptr == '@;'' return; ,irst_ptrMM; L char* last_ptr; // +he last letter o, the word M ( // 5ind last letter ,or &last_ptr = ,irst_ptrM(; isalpha&*last_ptr'; MMlast_ptr' continue; // 0e$erse word re$_chars&,irst_ptr) last_ptrN('; // Po$e to next ,irst_ptr = last_ptr M(; L L Good hackers "ill look ,eyond the i##ediate pro,le# and ask the =uestion /6hy are you doing such a thingS3 ;t #ay ,e that the "ords are ,eing consu#ed ,y so#e sort o) co##and parser "hich needs the# in reverse ;) that5s true, then there5s no reason to reverse the "ords, then ,reak the# apart in the co##and parse Yust #odi)y the co##and parser to ,reak a string apart into "ords in reverse order Great hackers not only are a,le to solve the pro,le# ,e)ore the#, ,ut look ,eyond it and provide solutions that a))ect the ,igger picture
Page 20?
Steve Oualline
% group o) hackers "ere "orking )or a govern#ent contractor translating a ,unch o) code )ro# one version o) YOE%$ to another "hen they ca#e across this very ,adly "ritten )unction !he )igured that they could re"rite it to ,e ,oth cleaner and #ore e))icient ;n order to #ake sure that their ne" design "orked "ith the e&isting code, they searched the code to )ind every place "here the )unction "as called !hey )ound none Gothing !he )unction "as never called So they "ent to the ,oss and said, /!his )unction is never used, "e can get rid o) it 3 !he ,oss told the# that he kne" the )unction "as never used ;t hadn5t ,een called )or at least three releases @ut ,ecause this "as a govern#ent progra#, the cost o) doing the paper"ork )ar e&ceeded the cost o) paying so#eone to update it
C++ Hackers Guide next_ptr = cur_ptrNHlin8 c pre$_ptr; pre$_ptr = cur_ptr; cur_ptr = next_ptr; L
Steve Oualline
% si#ilar syste# can ,e used to go through the list in reverse !here are a )e" casts and a lot o) details o#itted )ro# this code %lso ;5# going to let the reader )igure out to insert and re#ove noted Ho"ever these days, #e#ory is cheap, progra##ers are e&pensive, and it5s )ar #ore cost e))ective to i#ple#ent a dou,le linked list as a dou,le linked list, so this is Kust an acade#ic e&ercise
!his algorith# uses the )ollo"ing code to enter the critical section and access the shared resource* 1 Set a flag indicating that this process is no" atte#pting to enter the critical section 2 Set the tu(n varia,le to indicate that this process "ants in !he tu(n varia,le "ill hold the ;9 o) the last process to atte#pt entry 4 ;) the other process "ants the critical section and "e "ere the last one to access the tu(n varia,le, "ait 0% CP. consu#ing spin "ait is used in this e&a#ple 2 > 9o the critical stu)) ? Set the flag to indicate that "e are no longer in the critical section // Index ,or ,lag and turn $aria#les enu: process K30/.!66_( = ;) 30/.!66_* = (L; // I, true) I': tr%ing to go critical $olatile #ool ,lagT*U = K,alse) ,alseL; // -ho's turn is it now Page 20B Copyright 2008, Steve Oualline
C++ Hackers Guide $olatile int turn = 30/.!66_(; $oid process_(&' K ,lagT30/.!66_(U = true; turn = 30/.!66_(; while &,lagT30/.!66_*U >> &turn == 30/.!66_('' continue; // do nothing do_critical&'; ,lagT30/.!66_(U = ,alse; L $oid process_*&' K ,lagT30/.!66_*U = true; turn = 30/.!66_*; while &,lagT30/.!66_(U >> &turn == 30/.!66_*'' continue; // do nothing do_critical&'; ,lagT30/.!66_*U = ,alse; L
Steve Oualline
%s hackers "e tend to think ,eyond the ,oundaries o) the pro,le# ;n this e&a#ple "e care)ul to use the volatile key"ord to #ake sure that the #e#ory "as actually changed and that the opti#iFer didn5t play ga#es "ith our code @ut hard"are can play tricks on us too $et5s suppose these processes are running on di))erent CP.s ;) the processors have caches, the changes to flag and tu(n could ,e #ade in a local cache only and not copied to the shared #e#ory ;) this is the case "e need to add so#e cache )lush instructions to this syste# !here are other =uestions to ask as "ell, such as "hy "e don5t have a so#e sort o) hard"are locking #echanis#, or at least a test and set instruction !here are a lot o) unans"ered =uestions to think a,out @ut this pro,le# is a good e&ercise "hen it co#es to )iguring out all the )unny things that can happen in #ultiple process progra##ing (ou have to ,e a"are that any process can run at any ti#e and any shared varia,le can change at any ti#e to ,e really e))ective "hen it co#es to this type o) progra##ing
Page 208
Steve Oualline
Steve Oualline
!here are so#e other things to note a,out this progra# 'irst the C version o) this code is e&actly the sa#e as the C++ one On .G;T this "as originally i#ple#ented as a shell script containing 0 lines On #y Solaris ,o&, it is a shell script "hich has in it nothing ,ut )ive copyright notices, a "arning telling #e that the contents are unpu,lished prosperity code, and a version nu#,er* 1 A Go co##ands !he version nu#,er is #ost interesting, since the script contains no code 6hat did they get "rong in versions 1 0 through 1 ? that got )i&ed in 1 AS !he version o) the co##and that ships "ith $inu& contains options One prints out the version nu#,er o) the co##and, the other prints out a help te&t that tells you that the only option is the one to print out the version nu#,er ;ncidentally the version nu#,er on #y syste# is ? 2 1 %gain one has to "onder "hat "as "rong "ith the previous versionsS So the true co##and serves t"o purposes One it sho"s ho" a,solute state#ents such as /; can #ake it ,etter "ith o,Kects3 aren5t al"ays true %nd it also sho"s ho" #anagers, copyright la"yers, and other )orces can add needless co#ple&ity to a progra# that the closest thing to a nothing progra# that ; kno" o)
Page 210
Steve Oualline
Grace Hopper
;nventor o) the )irst co#piler 0CO@O$2 and "ell kno"n )or )inding a #oth ,eaten to death ,y the contacts o) a relay ,ased co#puter 0!his incident has given rise to the legend 0incorrect2 that this "as the )irst co#puter ,ug2 Page 211 Copyright 2008, Steve Oualline
Steve Oualline
!he "onder)ul thing a,out standards is that there are so #any o) the# to choose )ro# U!he #ost da#aging phrase in the language is* 6e5ve al"ays done it this "ay U ;) it5s a good idea, go ahead and do it ;t5s #uch easier to apologiFe than it is to get per#ission
Lin%s )or1alds
%uthor o) $inu&
%ny progra# is only as good as it is use)ul ;5# generally a very prag#atic person* that "hich "orks, "orks ;n #any cases, the user inter)ace to a progra# is the #ost i#portant part )or a co##ercial co#pany* "hether the progra#s "orks correctly or not see#s to ,e secondary $inu& tends to have )e"er rules than other develop#ents, and any,ody can chip in doing "hatever they "ant 8icroso)t isn5t evil, they Kust #ake really crappy operating syste#s !he cy,erspace earnings ; get )ro# $inu& co#e in the )or#at o) having a Get"ork o) people that kno" #e and trust #e, and that ; can depend on in return !he #e#ory #anage#ent on the Po"erPC can ,e used to )righten s#all children See, you not only have to ,e a good coder to create a syste# like $inu&, you have to ,e a sneaky ,astard too ;) you need #ore than 4 levels o) indentation, you5re scre"ed any"ay, and should )i& your progra# (ou kno" you5re ,rilliant, ,ut #ay,e you5d like to understand "hat you did 2 "eeks )ro# no" !alk is cheap Sho" #e the code -eally, ;5# not out to destroy 8icroso)t !hat "ill Kust ,e a co#pletely unintentional side e))ect
Page 212 Copyright 2008, Steve Oualline
Steve Oualline
!he )act that %CP; "as designed ,y a group o) #onkeys high on $S9, and is so#e o) the "orst designs in the industry o,viously #akes running it at any point pretty da#n ugly Given enough eye,alls, all ,ugs are shallo" ; "ill, in )act, clai# that the di))erence ,et"een a ,ad progra##er and a good one is "hether he considers his code or his data structures #ore i#portant @ad progra##ers "orry a,out the code Good progra##ers "orry a,out data structures and their relationships
Page 214
Steve Oualline
Page 21>
C++ Hackers Guide Grace Oualline 0%ge 42 you5ve ever use the ter# !CP1;P during a date
Steve Oualline
your "i)e has stood naked ne&t to the co#puter and asked you U9o you "ant to "ork on the co#puter or #ake loveSU and you had to think a,out the ans"er you thought a,out the ans"er then decided to )i& Kust one #ore ,ug you5ve edited a progra# on a laptop you ,rought to 9isneyland played co#puter ga#es )or less than an hour ,e)ore trying to disasse#,le the thing to )igure out ho" it "orked once you )igured out ho" the ga#e "orked, decided to i#prove it "ired a household appliance to a co#puter ever said /; no" kno" the di))erence ,et"een ` and ``3 to so#eone "ho understood e&actly "hat you #eant 0` is pronounced /and3 2
Page 21?
Steve Oualline
=o Comments
;5ve heard that the ne&t great progra##ing language is going to ,e so easy to "rite in that you "on5t need co##ents .n)ortunately ; heard that 40 years ago and the language in =uestion "as 'O-!-%G ;; !hey also said it a,out CO@O$ !hey "ere "rong :nglish is still one o) the ,est "ays o) co##unicating "ith people Got using it to e&plain "hat you do #eans that you5ve created a cryptic #ess "hich can5t ,e shared ,y other people
IncOnsisTencY
6hen you progra# consistently you create patterns "hich allo" other people to easily understand and aug#ent your code ;nconsistency creates con)usion and disrupts the "ork process 0;nconsistency is ,ook "riting #eans that you have to e&plain to copy editor "hy your strange )or#atting is really Kust an atte#pt to hu#or !hey keep #issing the Koke and trying to )i& it 2
Page 21A
Steve Oualline
Page 21B
Steve Oualline
do&!*en
% syste# )or e#,edding docu#entation inside a C or C++ progra# 0as "ell as so#e other languages 2 6hen used on a "hole syste# this is a very e))ective tool )or generating code docu#entation %vaila,le )ro# http*11""" do&ygen org
#la"#inder
%nalyFes code )or potential security pro,le#s %vaila,le )ro# http*11""" d"heeler co#1)la")inder1
l&r
$inu& cross re)erence %ctually this tool "ill cross re)erence any progra# and produce a set o) hyperClinked )iles "hich #ake it easy to navigate through large progra#s !he progra# can o,tained at* http*11l&r linu& no1
Page 218
Steve Oualline
2? People "ho love the :8%CS editor and others #ay dispute this clai#
Page 217
Steve Oualline
3E De,inin* Constants
.se const i) possi,le* const int -I7+I = F;; ;) you #ust use &define put the value in 02* Jde,ine A0!A &F; * (;'
Page 220
Steve Oualline
.E -e o01io%s a0o%t e1er!thin* !o% do> e1en nothin* ,or &i = ;; #u,,erTiU R= 'x'; MMi' continue; switch &state' K case (: do_stage_(&'; // 5all throught case *: do_stage_*&'; #rea8; de,ault: // 6hould ne$er happen assert&I:possi#le state == ;'; a#ort&'; L /E 7l"a!s check ,or the de,a%lt case in a s"itch
See a,ove
2E 'recedence R%les
1 8ultiply 0H2 and divide 012 co#e ,e)ore addition 0+2 and su,traction 0C2
Page 221
Steve Oualline
3E Header #iles
%l"ays include your o"n header )ile /* 5ile: report=c */ === Jinclude report=h Protect against dou,le inclusion* /* 5ile report=h */ Ji,nde, __0!3/0+_I__ Jde,ine __0!3/0+_I__ // ==== Jendi, /* __0!3/0+_I__ */
Steve Oualline
13E When creatin* opa$%e t!pes> make them checka0le 0! the compiler
struct ,ont_handle K int handle; L; struct window_handle K int handle; L struct :e:or%_handle K int handle; L
Steve Oualline
Page 22>
Steve Oualline
Steve Oualline
) <>ou< #eans an individual or entity e&ercising rights under this $icense "ho has not previously violated the ter#s o) this $icense "ith respect to the 6ork, or "ho has received e&press per#ission )ro# the $icensor to e&ercise rights under this $icense despite a previous violation "6 1air ?se -ights6 Gothing in this license is intended to reduce, li#it, or restrict any rights arising )ro# )air use, )irst sale or other li#itations on the e&clusive rights o) the copyright o"ner under copyright la" or other applica,le la"s #6 License )rant6 Su,Kect to the ter#s and conditions o) this $icense, $icensor here,y grants (ou a "orld"ide, royaltyC)ree, nonCe&clusive, perpetual 0)or the duration o) the applica,le copyright2 license to e&ercise the rights in the 6ork as stated ,elo"* a to reproduce the 6ork, to incorporate the 6ork into one or #ore Collective 6orks, and to reproduce the 6ork as incorporated in the Collective 6orks] , to create and reproduce 9erivative 6orks provided that any such 9erivative 6ork, including any translation in any #ediu#, takes reasona,le steps to clearly la,el, de#arcate or other"ise identi)y that changes "ere #ade to the original 6ork 'or e&a#ple, a translation could ,e #arked U!he original "ork "as translated )ro# :nglish to Spanish,U or a #odi)ication could indicate U!he original "ork has ,een #odi)ied U]] c to distri,ute copies or phonorecords o), display pu,licly, per)or# pu,licly, and per)or# pu,licly ,y #eans o) a digital audio trans#ission the 6ork including as incorporated in Collective 6orks] d to distri,ute copies or phonorecords o), display pu,licly, per)or# pu,licly, and per)or# pu,licly ,y #eans o) a digital audio trans#ission 9erivative 6orks e 'or the avoidance o) dou,t, "here the 6ork is a #usical co#position* i Performance -oyalties ?nder +lanket Licenses $icensor "aives the e&clusive right to collect, "hether individually or, in the event that $icensor is a #e#,er o) a per)or#ance rights society 0e g %SC%P, @8;, S:S%C2, via that society, royalties )or the pu,lic per)or#ance or pu,lic digital per)or#ance 0e g "e,cast2 o) the 6ork
Page 22A
Steve Oualline
ii Mechanical -ights and 'tatutory -oyalties $icensor "aives the e&clusive right to collect, "hether individually or via a #usic rights agency or designated agent 0e g Harry 'o& %gency2, royalties )or any phonorecord (ou create )ro# the 6ork 0Ucover versionU2 and distri,ute, su,Kect to the co#pulsory license created ,y 1B .SC Section 11? o) the .S Copyright %ct 0or the e=uivalent in other Kurisdictions2 ) Webcasting -ights and 'tatutory -oyalties 'or the avoidance o) dou,t, "here the 6ork is a sound recording, $icensor "aives the e&clusive right to collect, "hether individually or via a per)or#anceCrights society 0e g Sound:&change2, royalties )or the pu,lic digital per)or#ance 0e g "e,cast2 o) the 6ork, su,Kect to the co#pulsory license created ,y 1B .SC Section 11> o) the .S Copyright %ct 0or the e=uivalent in other Kurisdictions2 !he a,ove rights #ay ,e e&ercised in all #edia and )or#ats "hether no" kno"n or herea)ter devised !he a,ove rights include the right to #ake such #odi)ications as are technically necessary to e&ercise the rights in other #edia and )or#ats %ll rights not e&pressly granted ,y $icensor are here,y reserved $6 -estrictions6 !he license granted in Section 4 a,ove is e&pressly #ade su,Kect to and li#ited ,y the )ollo"ing restrictions* a (ou #ay distri,ute, pu,licly display, pu,licly per)or#, or pu,licly digitally per)or# the 6ork only under the ter#s o) this $icense, and (ou #ust include a copy o), or the .ni)or# -esource ;denti)ier )or, this $icense "ith every copy or phonorecord o) the 6ork (ou distri,ute, pu,licly display, pu,licly per)or#, or pu,licly digitally per)or# (ou #ay not o))er or i#pose any ter#s on the 6ork that restrict the ter#s o) this $icense or the a,ility o) a recipient o) the 6ork to e&ercise the rights granted to that recipient under the ter#s o) the $icense (ou #ay not su,license the 6ork (ou #ust keep intact all notices that re)er to this $icense and to the disclai#er o) "arranties 6hen (ou distri,ute, pu,licly display, pu,licly per)or#, or pu,licly digitally per)or# the 6ork, (ou #ay not i#pose any technological #easures on the 6ork that restrict the a,ility o) a recipient o) the 6ork )ro# (ou to e&ercise the rights granted to that recipient under the ter#s o) the $icense !his Section >0a2 applies to the 6ork as incorporated in a Collective 6ork, ,ut this does not re=uire the Collective 6ork apart )ro# the 6ork itsel) to ,e #ade su,Kect to the ter#s o) this $icense ;) (ou create a Collective 6ork, upon notice )ro# any $icensor (ou #ust, to the e&tent practica,le, re#ove )ro# the Collective 6ork any credit as re=uired ,y Section >0,2, as re=uested ;) (ou create a 9erivative 6ork, upon notice )ro# any $icensor (ou #ust, to the e&tent practica,le, re#ove )ro# the 9erivative 6ork any credit as re=uired ,y Section >0,2, as re=uested Page 22B Copyright 2008, Steve Oualline
Steve Oualline
, ;) (ou distri,ute, pu,licly display, pu,licly per)or#, or pu,licly digitally per)or# the 6ork 0as de)ined in Section 1 a,ove2 or any 9erivative 6orks 0as de)ined in Section 1 a,ove2 or Collective 6orks 0as de)ined in Section 1 a,ove2, (ou #ust, unless a re=uest has ,een #ade pursuant to Section >0a2, keep intact all copyright notices )or the 6ork and provide, reasona,le to the #ediu# or #eans (ou are utiliFing* 0i2 the na#e o) the Original %uthor 0or pseudony#, i) applica,le2 i) supplied, and1or 0ii2 i) the Original %uthor and1or $icensor designate another party or parties 0e g a sponsor institute, pu,lishing entity, Kournal2 )or attri,ution 0U%ttri,ution PartiesU2 in $icensor5s copyright notice, ter#s o) service or ,y other reasona,le #eans, the na#e o) such party or parties] the title o) the 6ork i) supplied] to the e&tent reasona,ly practica,le, the .ni)or# -esource ;denti)ier, i) any, that $icensor speci)ies to ,e associated "ith the 6ork, unless such .-; does not re)er to the copyright notice or licensing in)or#ation )or the 6ork] and, consistent "ith Section 40,2 in the case o) a 9erivative 6ork, a credit identi)ying the use o) the 6ork in the 9erivative 6ork 0e g , U'rench translation o) the 6ork ,y Original %uthor,U or UScreenplay ,ased on original 6ork ,y Original %uthorU2 !he credit re=uired ,y this Section >0,2 #ay ,e i#ple#ented in any reasona,le #anner] provided, ho"ever, that in the case o) a 9erivative 6ork or Collective 6ork, at a #ini#u# such credit "ill appear, i) a credit )or all contri,uting authors o) the 9erivative 6ork or Collective 6ork appears, then as part o) these credits and in a #anner at least as pro#inent as the credits )or the other contri,uting authors 'or the avoidance o) dou,t, (ou #ay only use the credit re=uired ,y this Section )or the purpose o) attri,ution in the #anner set out a,ove and, ,y e&ercising (our rights under this $icense, (ou #ay not i#plicitly or e&plicitly assert or i#ply any connection "ith, sponsorship or endorse#ent ,y the Original %uthor, $icensor and1or %ttri,ution Parties, as appropriate, o) (ou or (our use o) the 6ork, "ithout the separate, e&press prior "ritten per#ission o) the Original %uthor, $icensor and1or %ttri,ution Parties %6 -epresentations@ Warranties and *isclaimer
Page 228
Steve Oualline
.G$:SS O!H:-6;S: 8.!.%$$( %G-::9 !O @( !H: P%-!;:S ;G 6-;!;GG, $;C:GSO- O'':-S !H: 6O-< %SC;S %G9 OG$( !O !H: :T!:G! O' %G( -;GH!S H:$9 ;G !H: $;C:GS:9 6O-< @( !H: $;C:GSO- !H: $;C:GSO- 8%<:S GO -:P-:S:G!%!;OGS O- 6%--%G!;:S O' %G( <;G9 COGC:-G;GG !H: 6O-<, :TP-:SS, ;8P$;:9, S!%!.!O-( O- O!H:-6;S:, ;GC$.9;GG, 6;!HO.! $;8;!%!;OG, 6%--%G!;:S O' !;!$:, 8%-<:!%@;$;!(, 8:-CH%G!;@;$;!(, ';!G:SS 'O- % P%-!;C.$%- P.-POS:, GOG;G'-;GG:8:G!, O- !H: %@S:GC: O' $%!:G! O- O!H:- 9:':C!S, %CC.-%C(, O- !H: P-:S:GC: O' %@S:GC: O' :--O-S, 6H:!H:- OGO! 9;SCOE:-%@$: SO8: Y.-;S9;C!;OGS 9O GO! %$$O6 !H: :TC$.S;OG O' ;8P$;:9 6%--%G!;:S, SO S.CH :TC$.S;OG 8%( GO! %PP$( !O (O. A6 Limitation on Liability6 :TC:P! !O !H: :T!:G! -:L.;-:9 @( %PP$;C%@$: $%6, ;G GO :E:G! 6;$$ $;C:GSO- @: $;%@$: !O (O. OG %G( $:G%$ !H:O-( 'O- %G( SP:C;%$, ;GC;9:G!%$, COGS:L.:G!;%$, P.G;!;E: O- :T:8P$%-( 9%8%G:S %-;S;GG O.! O' !H;S $;C:GS: O!H: .S: O' !H: 6O-<, :E:G ;' $;C:GSO- H%S @::G %9E;S:9 O' !H: POSS;@;$;!( O' S.CH 9%8%G:S B6 Termination a !his $icense and the rights granted hereunder "ill ter#inate auto#atically upon any ,reach ,y (ou o) the ter#s o) this $icense ;ndividuals or entities "ho have received 9erivative 6orks 0as de)ined in Section 1 a,ove2 or Collective 6orks 0as de)ined in Section 1 a,ove2 )ro# (ou under this $icense, ho"ever, "ill not have their licenses ter#inated provided such individuals or entities re#ain in )ull co#pliance "ith those licenses Sections 1, 2, ?, A, B, and 8 "ill survive any ter#ination o) this $icense , Su,Kect to the a,ove ter#s and conditions, the license granted here is perpetual 0)or the duration o) the applica,le copyright in the 6ork2 Got"ithstanding the a,ove, $icensor reserves the right to release the 6ork under di))erent license ter#s or to stop distri,uting the 6ork at any ti#e] provided, ho"ever that any such election "ill not serve to "ithdra" this $icense 0or any other license that has ,een, or is re=uired to ,e, granted under the ter#s o) this $icense2, and this $icense "ill continue in )ull )orce and e))ect unless ter#inated as stated a,ove C6 Miscellaneous
Page 227
Steve Oualline
a :ach ti#e (ou distri,ute or pu,licly digitally per)or# the 6ork 0as de)ined in Section 1 a,ove2 or a Collective 6ork 0as de)ined in Section 1 a,ove2, the $icensor o))ers to the recipient a license to the 6ork on the sa#e ter#s and conditions as the license granted to (ou under this $icense , :ach ti#e (ou distri,ute or pu,licly digitally per)or# a 9erivative 6ork, $icensor o))ers to the recipient a license to the original 6ork on the sa#e ter#s and conditions as the license granted to (ou under this $icense c ;) any provision o) this $icense is invalid or unen)orcea,le under applica,le la", it shall not a))ect the validity or en)orcea,ility o) the re#ainder o) the ter#s o) this $icense, and "ithout )urther action ,y the parties to this agree#ent, such provision shall ,e re)or#ed to the #ini#u# e&tent necessary to #ake such provision valid and en)orcea,le d Go ter# or provision o) this $icense shall ,e dee#ed "aived and no ,reach consented to unless such "aiver or consent shall ,e in "riting and signed ,y the party to ,e charged "ith such "aiver or consent e !his $icense constitutes the entire agree#ent ,et"een the parties "ith respect to the 6ork licensed here !here are no understandings, agree#ents or representations "ith respect to the 6ork not speci)ied here $icensor shall not ,e ,ound ,y any additional provisions that #ay appear in any co##unication )ro# (ou !his $icense #ay not ,e #odi)ied "ithout the #utual "ritten agree#ent o) the $icensor and (ou
C++ Hackers Guide this trade#ark restriction does not )or# part o) the $icense
Steve Oualline
Page 241