FAQ's of C Programming Q1. main() { int i; clrscr(); printf("%d", &i)+1; scanf("%d", i)-1; } a. Runtime error. . Runtime error. !ccess iolation. c. #ompile error. $lleal snta' d. one of te aoe !ns* d, printf( printf( ) prints prints addressar addressarae ae of i, scanf() dont a & sin, so scans address for i +1, -1 dont a an effect on code Q. main(int arc, car ar/) { (main && arc) 0 main(arc-1, 22) * return 3; } a. Runtime error. . #ompile error. $lleal snta' c. 4ets into $nfinite loop d. one of te aoe !ns* ) illeal illeal snta' snta' for usin usin return return Q5. main() { int i; float pf; pf 6 (float )&i; pf 6 133.33; printf("7n %d", i); } a. Runtime error. . 133 c. 8ome $nteer not 133 d. one of te aoe !ns* d) 3 Q9. main()
{ int i 6 3'ff ; printf("7n%d", i::); } a. 9 . 1 c. 133 d. 139 !ns* c) 133 133 Q. <define 8QR(') ' ' main() { printf("%d", 8QR(1)); } a. 1 . c. 1 d. none of te aoe !ns* ) Q=. union u { struct st { int i * 9; int > * 9; int ? * 9; int l; }st; int i; }u; main() { u.i 6 133; printf("%d, %d, %d",u.i, u.st.i, u.st.l); } a. 9, 9, 3 . 3, 3, 3 c. 133, 9, 3 d. 93, 9, 3 !ns* c) 133, 133, 9, 3 Q@. union u
{ union u { int i; int >; }a13/; int 13/; }u; main() { printf("7n%d", siAeof(u)); printf(" %d", siAeof(u.a)); printf("%d", siAeof(u.a9/.i)); } a. 9, 9, 9 . 93, 9, 9 c. 1, 133, 1 d. 93 933 9 !ns* 3, 33, error error for 5rd printf QB. main() { int (functale/)(car format, ...) 6{printf, scanf}; int i 6 133; (functale3/)("%d", i); (functale1/)("%d", i); (functale1/)("%d", i); (functale3/)("%d", &i); } a. 133, Runtime error. . 133, Random numer, Random numer, Random numer. c. #ompile error d. 133, Random numer QC. main() { int i, >, p; i 6 ; > 6 133; p 6 &i; !ddress of i is assined to pointer p printf("%f", i(p) ); i is diided pointer p } a. Runtime error. . 1.33333 c. #ompile error d. 3.33333
!ns* c) Drror Drror ecoA ecoA i(p) is i.e 1 Eic Eic is int & printed as a float, float, 8o anormal proram termination, runs if (float) i(p) -----F Gpe #astin Q13. main() { int i, >; scanf("%d %d"+scanf("%d %d", &i, &>)); printf("%d %d", i, >); } a. Runtime error. . 3, 3 c. #ompile error d. te first tEo alues entered te user !ns* d) tEo tEo alues alues entered, entered, 5rd Eill Eill e null null pointer assinment assinment Q11. main() { car p 6 "ello Eorld"; p3/ 6 HIH; printf("%s", p); } a. Runtime error. . "Iello Eorld" c. #ompile error d. "ello Eorld" !ns* ) Iello Iello Eorld Eorld Q1. main() { car str!; car strJ 6 $ am KL; memcp( str!, strJ, =); } a. Runtime error. . $ am KL c. #ompile error d. $ am K !ns* c) $ am KL is not in " " Q15. IoE Eill ou print % caracter0 a. printf("7%") . printf("77%") c. printf("%%") d. printf("7%%")
!ns* c) printf(" %% "); Q19. const int perple'ed 6 ; <define perple'ed 5 main() { <ifdef perple'ed <undef perple'ed <define perple'ed 9 <endif printf("%d",perple'ed); } a. 3 . c. 9 d. none of te aoe !ns* c) Q1. struct Moo { car pame; }; main() { struct Moo o> 6 malloc(siAeof(struct Moo)); clrscr(); strcp(o>-Fpame,"Nour ame"); printf("%s", o>-Fpame); } a. Nour ame . compile error c. ame d. Runtime error !ns a) Q1=. struct Moo { car pame; car p!ddress; }; main() { struct Moo o> 6 malloc(siAeof(struct Moo)); clrscr(); o>-Fpame 6 malloc(133);
o>-Fp!ddress 6 malloc(133); strcp(o>-Fpame,"Nour ame"); strcp(o>-Fp!ddress, "Nour !ddress"); free(o>); printf("%s", o>-Fpame); printf("%s", o>-Fp!ddress); } a. Nour ame, Nour !ddress . Nour !ddress, Nour !ddress c. Nour ame Nour ame d. one of te aoe !ns* d) printd otin, as after free(o>), no memor is tere containin o>-Fpame & p>-Fp!ddress Q1@. main() { car a 6 "Iello "; car 6 "Oorld"; clrscr(); printf("%s", strcat(a,)); } a. Iello . Iello Oorld c. IelloOorld d. one of te aoe !ns* ) Q1B. main() { car a 6 "Iello "; car 6 "Oorld"; clrscr(); printf("%s", strcp(a,)); } a. "Iello" . "Iello Oorld" c. "IelloOorld" d. one of te aoe !ns* d) Oorld, copies Oorld on a, oerErites Iello in a. Q1C. oid func1(int (a)13/) { printf("K? it Eor?s"); } oid func(int a/13/)
{ printf("Oill tis Eor?0"); } main() { int a13/13/; func1(a); func(a); } a. K? it Eor?s . Oill tis Eor?0 c. K? it Eor?sOill tis Eor?0 d. one of te aoe !ns* c) Q3. main() { printf("%d, %d", siAeof(HcH), siAeof(133)); } a. , . , 133 c. 9, 133 d. 9, 9 !ns* a) , Q1. main() { int i 6 133; clrscr(); printf("%d", siAeof(siAeof(i))); } a. . 133 c. 9 d. none of te aoe !ns* a) Q. main() { int c 6 ; printf("%d", mainPPc); } a. 1
. c. 3 d. none of te aoe !ns* a) 1, if Ee use mainPc ten error, illeal use of pointer Q5. main() { car c; int i 6 9=; clrscr(); c 6 i; printf("%d", c); } a. 9= . -9= c. random numer d. none of te aoe !ns* d) -= Q9. oid main () { int ' 6 13; printf ("' 6 %d, 6 %d", ',--'++); } a. 13, 13 . 13, C c. 13, 11 d. none of te aoe !ns* d) 2alue reuired Q. main() { int i 613, > 6 3; clrscr(); printf("%d, %d, ", >-- , --i); printf("%d, %d ", >++ , ++i); } a. 3, 13, 3, 13 . 3, C, 3, 13 c. 3, C, 1C, 13 d. 1C, C, 3, 13 !ns* c) Q=. main() { int '6;
clrscr(); for(;'663;'--) { printf("'6%d7n"", '--); } } a. 9, 5, , 1, 3 . 1, , 5, 9, c. 3, 1, , 5, 9 d. none of te aoe !ns* d) prints notin, as condition '663 is Malse Q@ main() { int '6; for(;'63;'--) { printf("'6%d7n", '--); } } a. , 9, 5, ,1 . 9, 5, , 1, 3 c. , 5, 1 d. none of te aoe !ns* d) $nfinite loop as ' is decremented tEice, it neer e 3 and loop is oin on & on QB main() { int '6; clrscr(); for(;':6 3;'--) { printf("'6%d ", '--); } } a. , 5, 1 . , , 1, c. , 5, 1, -1, 5 d. -5, -1, 1, 5, !ns* prints notin, as condition in loop is false. QC. main() { {
unsined int it6=; printf("%d", it); } { unsined int it61; printf("%d", it); } } a. =, = . 1, 1 c. =, 1 d. #ompile error !ns* =, 1, ecoA tese r different loc?s, so declaration alloEed Q53. main() { int i; clrscr(); for(i63;i:;i++) { printf("%d7n", 12 :: i); } } a. , 9, 5, , 1 . 3, 1, , 5, 9 c. 3, 1, , 9, B d. 1, , 9, B, 1= !ns* d) 2 doesHt ma?e an diff. Q51. main() { sined int it61, i6; for(;i;i--) { printf("%d7n", it 6 (it FF (i - (i -1)))); } } a. 1, =, 1B, =9, 5 . =, 1B, =9, 5, 1= c. 1B, =9, 5, 1=, B d. =9, 5, 1=, B, 9 !ns* ) Q5. main() {
sined int it61, i6; for(;i;i--) { printf("%d7n", it FF (i - (i -1))); } } a. 1, =, 3, 3, 3 . =, =, 3, 3, 3 c. 1, 1, 1, 1, 1 d. =, =, =, =, = !ns* d) itHs alue is not caned Q55. main() { if ((1&&3)) { printf("KL $ am done."); } else { printf("KL $ am one."); } } a. KL $ am done . KL $ am one c. compile error d. none of te aoe !ns* a) Q59 main() { if ((1PP3) && (3PP1)) { printf("KL $ am done."); } else { printf("KL $ am one."); } } a. KL $ am done . KL $ am one c. compile error d. none of te aoe
!ns* a) Q5 main() { sined int it61, mJit; { mJit 6 Sit; it 6 it & Sit ; printf("%d %d", it, mJit); } } a. 3, 3 . 3, 15 c. 1, 3 d. 3, -15 !ns* d)
C++
FAQ's of C++, OOPS and Programming IoE do ou Erite a proram Eic produces its oEn source code as its output0 IoE can $ find te da of te Eee? ien te date0 O doesnHt # ae nested functions0 Oat is te most efficient Ea to count te numer of its Eic are set in a alue0 IoE can $ conert inteers to inar or e'adecimal0 IoE can $ call a function, ien its name as a strin0 IoE do $ access command-line aruments0 IoE can $ return multiple alues from a function0 IoE can $ ino?e anoter proram from Eitin a # proram0
IoE can $ access memor located at a certain address0 IoE can $ allocate arras or structures ier tan =9L0 IoE can $ find out oE muc memor is aailale0 IoE can $ read a director in a # proram0 IoE can $ increase te alloEale numer of simultaneousl open files0 OatHs Eron Eit te call "fopen("c*7neEdir7file.dat", "r")"0 Oat is te output of printf("%d") Oat Eill appen if $ sa delete tis Tifference etEeen "# structure" and "#++ structure". Tiffrence etEeen a "assinment operator" and a "cop constructor" Oat is te difference etEeen "oerloadin" and "oerriddin"0 D'plain te need for "Uirtual Testructor". #an Ee ae "Uirtual #onstructors"0 Oat are te different tpes of polmorpism0 Oat are Uirtual Munctions0 IoE to implement irtual functions in "#" Oat are te different tpes of 8torae classes0 Oat is amespace0 Oat are te tpes of 8G2 containers0. Tifference etEeen "ector" and "arra"0 IoE to Erite a proram suc tat it Eill delete itself after e'ectution0 #an Ee enerate a #++ source code from te inar file0 Oat are inline functions0 Gal? sometimin aout profilin0
IoE man lines of code ou ae Eritten for a sinle proram0 Oat is "strstream" 0 IoE to Erite Vultitreaded applications usin #++0 D'plain "passin alue", "passin pointer" and "passin reference" Orite an small proram tat Eill compile in "#" ut not in "#++" Iae ou eard of "mutale" ?eEord0 Oat is a "RGG$"0 $s tere sometin tat $ can do in # and not in #++0 O preincrement operator is faster tan postincrement0 Oat is te difference etEeen "calloc" and "malloc"0 Oat Eill appen if $ allocate memor usin "neE" and free it usin "free" or allocate sin "calloc" and free it usin "delete"0 Oat is Vemor !linment0 D'plain Eor?in of printf. Tifference etEeen "printf" and "sprintf". Oat is "map" in 8G20 Oen sall $ use Vultiple $neritance0 Oat are te tecniues ou use for deuin0 IoE to reduce a final siAe of e'ecutale0 4ie e'amples of a code optimiAation. Oat is ineritance0 Tifference etEeen #omposition and !reation. Tifference* 8euence Tiarams, #ollaoration Tiarams.
Tifference* HusesH, He'tendsH, HincludesH Oat sall $ o for Wac?ae Tiaram0 Oat is Wolmorpism0 $s class an K>ect0 $s o>ect a class0 #omment* #++ "includes" eaior and >aa "imports" Oat do ou mean "RealiAation"0 Oat is a Wresistent, Gransient K>ect0 Oat is te use of Kperator Kerloadin0 Toes V2 uarantee pro>ect success0 Tifference* !ctiit Tiaram and 8euence Tiaram. Oat is association0 IoE to resole man to man relationsip0 IoE do ou represent static memers and astract classes in #lass Tiaram0 Oat does static ariale mean0 Oat is a pointer0 Oat is a structure0 Oat are te differences etEeen structures and arras0 $n eader files Eeter functions are declared or defined0 Oat are te differences etEeen malloc() and calloc()0 Oat are macros0 Eat are its adantaes and disadantaes0 Tifference etEeen pass reference and pass alue0 Oat is static identifier0 Oere are te auto ariales stored0
Oere does loal, static, local, reister ariales, free memor and # Wroram instructions et stored0 Tifference etEeen arras and lin?ed list0 Oat are enumerations0 Tescrie aout storae allocation and scope of loal, e'tern, static, local and reister ariales0 Oat are reister ariales0 Oat are te adantae of usin reister ariales0 Oat is te use of tpedef0 #an Ee specif ariale field Eidt in a scanf() format strin0 $f possile oE0 Kut of fets() and ets() Eic function is safe to use and E0 Tifference etEeen strdup and strcp0 Oat is recursion0 Tifferentiate etEeen a for loop and a Eile loop0 Oat are it uses0 Oat are te different storae classes in #0 Orite doEn te euialent pointer e'pression for referrin te same element ai/>/?/l/0 Oat is difference etEeen 8tructure and nions0 Oat te adantaes of usin nions0 Oat are te adantaes of usin pointers in a proram0 Oat is te difference etEeen 8trins and !rras0 $n a eader file Eeter functions are declared or defined0 Oat is a far pointer0 Eere Ee use it0 IoE Eill ou declare an arra of tree function pointers Eere eac function receies tEo ints and returns a float0
Eat is a 22 Wointer0 Oeter it is same as an uninitialiAed pointer0 Oat is a 22 Vacro0 Oat is te difference etEeen a 22 Wointer and a 22 Vacro0 Oat does te error Hull Wointer !ssinmentH mean and Eat causes tis error0 Oat is near, far and ue pointers0 IoE man tes are occupied tem0 IoE Eould ou otain sement and offset addresses from a far address of a memor location0 !re te e'pressions arr and &arr same for an arra of inteers0 Toes mentionin te arra name ies te ase address in all te conte'ts0 D'plain one metod to process an entire strin as one unit0 Oat is te similarit etEeen a 8tructure, nion and enumeration0 #an a 8tructure contain a Wointer to itself0 IoE can Ee cec? Eeter te contents of tEo structure ariales are same or not0 IoE are 8tructure passin and returnin implemented te complier0 IoE can Ee readErite 8tructures fromto data files0 Oat is te difference etEeen an enumeration and a set of pre-processor < defines0 Eat do te HcH and HH in arc and ar stand for0 !re te ariales arc and ar are local to main0 Oat is te ma'imum comined lent of command line aruments includin te space etEeen ad>acent aruments0 $f Ee Eant tat an Eildcard caracters in te command line aruments sould e appropriatel e'panded, are Ee reuired to ma?e an special proision0 $f es, Eic0 Toes tere e'ist an Ea to ma?e te command line aruments aailale to oter functions Eitout passin tem as aruments to te function0
Oat are it fields0 Oat is te use of it fields in a 8tructure declaration0 Go Eic numerin sstem can te inar numer 1131133133111133 e easil conerted to0 Oic it Eise operator is suitale for cec?in Eeter a particular it is on or off0 Oic it Eise operator is suitale for turnin off a particular it in a numer0 Oic it Eise operator is suitale for puttin on a particular it in a numer0 Oic it Eise operator is suitale for cec?in Eeter a particular it is on or off0 Eic one is euialent to multiplin *2eft siftin a numer 1 or 2eft siftin an unsined int or car 10 Orite a proram to compare tEo strins Eitout usin te strcmp() function. Orite a proram to concatenate tEo strins. Orite a proram to intercane ariales Eitout usin te tird one. Orite prorams for 8trin Reersal & Walindrome cec? Orite a proram to find te Mactorial of a numer Orite a proram to enerate te Miinocci 8eries Orite a proram Eic emplos Recursion Orite a proram Eic uses #ommand 2ine !ruments Orite a proram Eic uses functions li?e strcmp(), strcp()0 etc Oat are te adantaes of usin tpedef in a proram0 IoE Eould ou dnamicall allocate a one-dimensional and tEo-dimensional arra of inteers0 IoE can ou increase te siAe of a dnamicall allocated arra0
IoE can ou increase te siAe of a staticall allocated arra0 Oen reallocatin memor if an oter pointers point into te same piece of memor do ou ae to read>ust tese oter pointers or do te et read>usted automaticall0 Oic function sould e used to free te memor allocated calloc()0 IoE muc ma'imum can ou allocate in a sinle call to malloc()0 #an ou dnamicall allocate arras in e'panded memor0 Oat is o>ect file0 IoE can ou access o>ect file0 Oic eader file sould ou include if ou are to deelop a function Eic can accept ariale numer of aruments0 #an ou Erite a function similar to printf()0 IoE can a called function determine te numer of aruments tat ae een passed to it0 #an tere e at least some solution to determine te numer of aruments passed to a ariale arument list function0 IoE do ou declare te folloEin* !n arra of tree pointers to cars !n arra of tree car pointers ! pointer to arra of tree cars ! pointer to function Eic receies an int pointer and returns a float pointer ! pointer to a function Eic receies notin and returns notin Oat do te functions atoi(), itoa() and ct() do0 Toes tere e'ist an oter function Eic can e used to conert an inteer or a float to a strin0 IoE Eould ou use sort() function to sort an arra of structures0
IoE Eould ou use sort() function to sort te name stored in an arra of pointers to strin0 IoE Eould ou use searc() function to searc a name stored in arra of pointers to strin0 IoE Eould ou use te functions sin(), poE(), srt()0 IoE Eould ou use te functions memcp(), memset(), memmoe()0 IoE Eould ou use te functions fsee?(), freed(), fErite() and ftell()0 IoE Eould ou otain te current time and difference etEeen tEo times0 IoE Eould ou use te functions randomiAe() and random()0 IoE Eould ou implement a sustr() function tat e'tracts a su strin from a ien strin0 Oat is te difference etEeen te functions rand(), random(), srand() and randomiAe()0 Oat is te difference etEeen te functions memmoe() and memcp()0 IoE do ou print a strin on te printer0 #an ou use te function fprintf() to displa te output on te screen0 Oat is an o>ect0 Oat is te difference etEeen an o>ect and a class0 Oat is te difference etEeen class and structure0 Oat is pulic, protected, priate0 Oat are irtual functions0 Oat is friend function0 Oat is a scope resolution operator0 Oat do ou mean ineritance0 Oat is astraction0
Oat is polmorpism0 D'plain Eit an e'ample. Oat is encapsulation0 Oat do ou mean indin of data and functions0 Oat is function oerloadin and operator oerloadin0 Oat is irtual class and friend class0 Oat do ou mean inline function0 Oat do ou mean pulic, priate, protected and friendl0 Oen is an o>ect created and Eat is its lifetime0 Oat do ou mean multiple ineritance and multileel ineritance0 Tifferentiate etEeen tem. Tifference etEeen realloc() and free0 Oat is a template0 Oat are te main differences etEeen procedure oriented lanuaes and o>ect oriented lanuaes0 Oat is R G G $ 0 Oat are eneric functions and eneric classes0 Oat is namespace0 Oat is te difference etEeen pass reference and pass alue0 O do Ee use irtual functions0 Oat do ou mean pure irtual functions0 Oat are irtual classes0 Toes c++ support multileel and multiple ineritance0 Oat are te adantaes of ineritance0 Oen is a memor allocated to a class0
Oat is te difference etEeen declaration and definition0 Oat is irtual constructorsdestructors0 $n c++ tere is onl irtual destructors, no constructors. O0 Oat is late ound function call and earl ound function call0 Tifferentiate. IoE is e'ception andlin carried out in c++0 Oen Eill a constructor e'ecuted0 Oat is Tnamic Wolmorpism0 Orite a macro for sEappin inteers.
GC FAQ -- draft Common questions What is garbage collection? Garbage collection is a part of a language's runtime system, or an add-on library, perhaps assisted by the compiler, the hardware, the OS, or any combination of the three, that automatically determines what memory a program is no longer using, and recycles it for other use !t is also "nown as ##automatic storage $or memory% reclamation'' Why is it good? &anual memory management is $programmer-%time consuming, and error prone &ost programs still contain lea"s his is all doubly true with programs using e(ception-handling and)or threads ! second enefit of arae collection, less oious to people Eo aenHt used it, is tat relin on arae collection to manae memor simplifies te interfaces etEeen components (suroutines, liraries, modules, classes) tat no loner need e'pose memor manaement details ("Eo is responsile for recclin tis memor"). !s garbage collection slow? *ot necessarily &odern garbage collectors appear to run as uic"ly as manual storage allocators $mallocfree or neEdelete% Garbage collection probably will not run as uic"ly as customied memory allocator de signed for use in a specific
program On the other hand, the e(tra code reuired to ma"e manual memory management wor" properly $for e(ample, e(plicit reference counting% is often more e(pensie than a garbage collector would be Can ! use garbage collection with C or C++? .robably &odern $well-tested, efficient, non-pausing% garbage collectors are aailable that wor" with all but the most pathological C and C++ programs, including legacy code See GC, C, and C++ for more details /oes garbage collection cause my program's e(ecution to pause? *ot necessarily 0 ariety of algorithms allow garbage collection to proceed concurrently, incrementally, and $for some definitions of the term% in 1real time1 here are incremental garbage collectors that wor" with C and C++, for instance Where can ! get a C or C++ garbage collector? 2oehm-Weiser collector http3))realitysgicom)employees)boehm4mti)gchtml or ftp3))parcftp(ero(com)pub)gc)gchtml Great Circle from Geodesic Systems 5sales6geodesiccom7 or 899-:;9-8:88 or http3))wwwgeodesiccom) <ein Warne 5warne6directca7 or 899-=9=-=>=>
Folk myths • • • •
GC is necessarily slower than manual memory management GC will necessarily ma"e my program pause &anual memory management won't cause pauses GC is incompatible with C and C++
Folk truths •
• •
• • •
&ost allocated obects are dynamically referenced by a ery small number of pointers he most important small number is O*@ &ost allocated obects hae short lifetimes 0llocation patterns $sie distributions, lifetime distributions% are bursty, not uniform A& behaior matters Cache behaior matters 1Optimal1 strategies can fail miserably
GC, C, and C++ !hat do you mean, gar"age #olle#tion and C$ Rater tan usin malloc and free to otain and reclaim memor, it is possile to lin? in a arae collector and alloE it to reclaim unused memor automaticall. Gis usuall een Eor?s if malloc is replaced Eit te arae collectorHs allocator and free is replaced Eit a do-notin suroutine. Gis approac as Eor?ed Eit te X11 lirar, for instance. $t is also possile to proram in a stle Eere free still reclaims storae, ut te arae collector acts as a ac?stop, preentin lea?s tat mit oterEise occur. Gis stle as also een tested Eit man applications, and it Eor?s Eell. Ge adantae ere is tat Eere it is eas for te prorammer to manae memor, te prorammer manaes te memor, ut Eere it is not, te arae collector does te >o. Gis doesnHt necessaril run an faster tan free-doesnotin, ut it ma elp ?eep te eap smaller.
%o& is this ossi"le$ #-compatile arae collectors ?noE Eere pointers ma enerall e found (e.., "ss", "data", and stac?), and maintain eap data structures tat alloE tem to uic?l determine Eat it patterns mit e pointers. Wointers, of course, loo? li?e pointers, so tis euristic traces out all memor reacale trou pointers. Oat isnHt reaced, is reclaimed.
his doesn't sound (ery orta"le) !hat if * need to ort my #ode and there's no gar"age #olle#tor on the target latform$ 8ome of tis code is necessaril sstem-dependent, ut te features of most operatin sstems ae een enumerated, so arae collection for # is aailale almost eerEere. Gat is, portailit isnHt a prolem if te code as alread een ported, and it as. 8pea?in personall (tis is Taid #ase) itHs also not ard to port tese arae collectors to neE platforms; $He ported te Joem-Oeiser collector tEice mself, Een te code ad not et een ported to terril man platforms, and Een $ ad muc less e'perience Eit te loE-leel interfaces to arious operatin sstems.
!on't this lea(e "ugs in my rogram$ Gis depends on our point of ieE. sin a arae collector soles a lot of prolems for a prorammer, Eic ies a prorammer time to sole oter prolems, or lets te >o e finised faster. $tHs similar in flaor to floatin point aritmetic or irtual memor. Jot of tese sole a tedious prolem (scalin aritmetic, or pain unused data to dis?) tat a prorammer could, in principle, sole. 8ome specialiAed code is Eritten Eitout MW or UV support, ut in
practice, if tese features are aailale, people use tem. GeHre enerall >uded to e Eell Eort te cost. oE, if a proram is deeloped usin arae collection, and te collector is ta?en aEa, ten es, te result ma contain us in te form of memor lea?s. 8imilarl, if a proram is deeloped usin MW (or UV) and tat is ta?en aEa, tat proram, too, ma contain us. !lso in practice, man prorams tat use malloc and free alread lea? memor, so use of a arae collector can actuall reduce te numer of us in a proram, and do so muc more uic?l tan if te ad to e trac?ed doEn and fi'ed and. Gis is especiall true if te memor lea? is inerent in a lirar tat cannot e repaired.
Can't a de(ious C rogrammer "reak the #olle#tor$ #ertainl, ut most people ae etter Eas to spend teir time tan dreamin up Eas to rea? teir tools. Ge collector does rel on ein ale to locate copies of pointers somewhere in an address space, so certain tins EonHt Eor?. Mor instance, te XKRHd pointers tric? for compactl encodin a idirectional list cannot e used -- te pointers donHt loo? li?e pointers. $f a process Erites pointers to a file, and reads tem ac? aain, te memor referenced tose pointers ma ae een reccled. Vost prorams donHt do tese tins, so most prorams Eor? Eit a arae collector. Krdinar (leal) pointer aritmetic is tolerated arae collectors for #. *nsert more questions here -- send them to g#listie##)#om
!hat does a gar"age #olle#tor do a"out destru#tors$ ! destructor is some code tat runs Een an o>ect is aout to e freed. Kne of te main uses of destructors is to do manual memor manaement. Mor e'ample, te destructor for an o>ect ma recursiel free te o>ects it references. ! arae collector oiates te need for suc uses* $f an o>ect is arae, all te o>ects it references Eill also e arae if te are not referenced elseEere, and so te, too, Eill e freed automaticall. Gere remains te uestion of Eat to do Eit destructors tat do sometin oter tan assist in memor manaement. Gere are a couple of tpical uses. Kne use is for o>ects tat ae state outside te proram itself. Ge canonical e'ample is an o>ect tat refers to a file. Oen a file o>ect ecomes eliile for reclamation, te arae collector needs to ensure tat uffers are flused, te file is closed, and resources associated Eit te file are returned to te operatin sstem. !noter use is Eere a proram Eants to ?eep a list of o>ects tat are referenced elseEere. Ge proram ma Eant ?noE Eat o>ects are in e'istence for, sa, accountin purposes ut does not Eant te mecanism of accountin to preent o>ects from oterEise ein freed. Gere are seeral Eas of andlin suc situations*
> !n systems where the garbage collector is 1built in,1 it typically has special "nowledge of all the cases where outside resources can be referenced and can deal with them appropriately B &any GC systems hae a notion of a 1wea" pointer1 0 wea" pointer is one that is not considered as a reference by the garbage collector So if an obect is referenced only by wea" pointers, it is eligible for reclamation Wea" pointers can be used to implement the obect list e(ample : &any GC systems hae a notion of 1finaliation1 0n obect may be registered with the GC system so that when it is about to reclaim the obect, it runs a function on the obect that can perform necessary cleanups inaliation is fundamentally tric"y Some of the issues are3 > When does a finaliation function run, particularly with respect to when other finaliers run?D B What happens when registered obects reference each other?D : What happens if a finaliation function ma"es an obect not be garbage any more? here are no pat answers to these uestions
Smart Pointers - !hat, !hy, !hi#h$ Yonat Sharon
!hat are they$ 8mart pointers are o>ects tat loo? and feel li?e pointers, ut are smarter. Oat does tis mean0 Go loo? and feel li?e pointers, smart pointers need to ae te same interface tat pointers do* te need to support pointer operations li?e dereferencin (operator ) and indirection (operator -F). !n o>ect tat loo?s and feels li?e sometin else is called a pro' o>ect, or >ust pro'. Ge pro' pattern and its man uses are descried in te oo?s Tesin Watterns and Wattern Kriented 8oftEare !rcitecture. Go e smarter tan reular pointers, smart pointers need to do tins tat reular pointers donHt. Oat could tese tins e0 Wroal te most common us in #++ (and #) are related to pointers and memor manaement* danlin pointers, memor lea?s, allocation failures and oter >os. Iain a smart pointer ta?e care of tese tins can sae a lot of aspirin... Ge simplest e'ample of a smart pointer is autoYptr, Eic is included in te standard #++ lirar. Nou can find it in te eader :memorF, or ta?e a loo? at 8cott VeersH autoYptr implementation . Iere is part of autoYptrHs implementation, to illustrate Eat it does* template :class GF class auto.tr { G ptr;
!s ou can see, autoYptr is a simple Erapper around a reular pointer. $t forEards all meaninful operations to tis pointer (dereferencin and indirection). $ts smartness in te destructor* te destructor ta?es care of deletin te pointer. Mor te user of autoYptr, tis means tat instead of Eritin* oid foo() { 1yClass p(neE 1yClass); p-F2oSomething(); delete p; }
Nou can Erite* oid foo() { auto.tr :1yClassF p(neE 1yClass); p-F2oSomething(); }
!nd trust p to cleanup after itself. Oat does tis u ou0 8ee te ne't section.
!hy &ould * use them$ Kiousl, different smart pointers offer different reasons for use. Iere are some common reasons for usin smart pointers in #++.
!hy3 Less bugs Automati# #leanu) !s te code aoe illustrates, usin smart pointers tat clean after temseles can sae a feE lines of code. Ge importance ere is not so muc in te ?estro?es saed, ut in reducin te proailit for us* ou donHt need to rememer to free te pointer, and so tere is no cance ou Eill foret aout it. Automati# initiali4ation) !noter nice tin is tat ou donHt need to initialiAe te autoYptr to 22, since te default constructor does tat for ou. Gis is one less tin for te prorammer to foret. 2angling ointers) ! common pitfall of reular pointers is te danlin pointer* a pointer tat points to an o>ect tat is alread deleted. Ge folloEin code illustrates tis situation* 1yClass p(neE 1yClass); 1yClass 6 p; delete p; p-F2oSomething(); Oatc out p is noE danlin p 6 22; p is no loner danlin -F2oSomething(); Kuc is still danlin
Mor autoYptr, tis is soled settin its pointer to 22 Een it is copied* template :class GF auto.tr :GF& auto.tr :GF**oerator5(auto.tr :GF& rs) { if (tis 6 &rs) { delete ptr; ptr 6 rs.ptr; rs.ptr 6 22; } return tis; }
Kter smart pointers ma do oter tins Een te are copied. Iere are some possile strateies for andlin te statement 6 p, Eere p and are smart pointers* Create a new copy of the obect pointed by p, and hae point to this copy his strategy is implemented in copied4ptrh Ownership transfer 3 Eet both p and point to the same obect, but transfer the responsibility for cleaning up $1ownership1% from p to his strategy is implemented in owned4ptrh Reference counting 3 &aintain a count of the smart pointers that point to the same obect, and delete the obect when this count becomes ero So the statement F p causes the count of the obect pointed by p to increase by one his strategy is implemented in counted4ptrh Scott &eyers offers another reference counting implementation in his boo" &ore @ffectie C++ Reference linking 3 he same as reference counting, only instead of a count, maintain a circular doubly lin"ed list of all smart pointers that point to the same obect his strategy is implemented in lin"ed4ptrh Copy on write 3 se reference counting or lin"ing as long as the pointed obect is not modified When it is about to be modified, copy it and modify the copy his strategy is implemented in cow4ptrh •
•
•
•
•
!ll tese tecniues elp in te attle aainst danlin pointers. Dac as eac oEn enefits and liailities. Ge Which section of tis article discusses te suitailit of different smart pointers for arious situations.
Oat appens if To8ometin() troEs an e'ception0 !ll te lines after it Eill not et e'ecuted and p Eill neer et deleted $f EeHre luc?, tis leads onl to memor lea?s. IoEeer, V#lass ma free some oter resources in its destructor (file andles, treads, transactions, #KV references, mute'es) and so not callin it m cause seere resource loc?s.
$f Ee use a smart pointer, oEeer, p Eill e cleaned up Eeneer it ets out of scope, Eeter it Eas durin te normal pat of e'ecution or durin te stac? unEindin caused troEin an e'ception. Jut isnHt it possile to Erite e'ception safe code Eit reular pointers0 8ure, ut it is so painful tat $ dout anone actuall does tis Een tere is an alternatie. Iere is Eat ou Eould do in tis simple case* oid foo() { 1yClass p; tr { p 6 neE 1yClass; p-F2oSomething(); delete p; } catc (...) { delete p; troE; } }
oE imaine Eat Eould appen if Ee ad some ifHs and forHs in tere...
!hy3 Garbage collection 8ince #++ does not proide automatic arae collection li?e some oter lanuaes, smart pointers can e used for tat purpose. Ge simplest arae collection sceme is reference countin or reference lin?in, ut it is uite possile to implement more sopisticated arae collection scemes Eit smart pointers. Mor more information see te arae collection M!Q .
!hy3 Efficiency 8mart pointers can e used to ma?e more efficient use of aailale memor and to sorten allocation and deallocation time. ! common strate for usin memor more efficientl is cop on Erite (#KO). Gis means tat te same o>ect is sared man #KO pointers as lon as it is onl read and not modified. Oen some part of te proram tries to modif te o>ect ("Erite"), te #KO pointer creates a neE cop of te o>ect and modifies tis cop instead of te oriinal o>ect. Ge standard strin class is commonl implemented usin #KO semantics (see te :strinF eader). string s("Iello"); string t 6 s;
t and s point to te same uffer of caracters
t +6 " tere"; a neE uffer is allocated for t efore appendin " tere", so s is uncaned.
KptimiAed allocation scemes are possile Een ou can ma?e some assumptions aout te o>ects to e allocated or te operatin enironment. Mor e'ample, ou ma ?noE tat all te o>ects Eill ae te same siAe, or tat te Eill all lie in a sinle tread. !ltou it is possile to implement optimiAed
allocation scemes usin class-specific neE and delete operators, smart pointers ie ou te freedom to coose Eeter to use te optimiAed sceme for eac o>ect, instead of ain te sceme set for all o>ects of a class. $t is terefore possile to matc te allocation sceme to different operatin enironments and applications, Eitout modifin te code for te entire class.
!hy3 STL containers Ge #++ standard lirar includes a set of containers and aloritms ?noEn as te standard template lirar (8G2). 8G2 is desined to e generic (can e used Eit an ?ind of o>ect) and efficient (does not incur time oeread compared to alternaties). Go aciee tese tEo desin oals, 8G2 containers store teir o>ects alue. Gis means tat if ou ae an 8G2 container tat stores o>ects of class Jase, it cannot store of o>ects of classes deried from Jase. class 6ase { ... }; class 2eri(ed * pulic 6ase { ... }; 6ase ; 2eri(ed d; (e#tor :6aseF ; .ush."a#k(); KL .ush."a#k(d); error
Oat can ou do if ou need a collection of o>ects from different classes0 Ge simplest solution is to ae a collection of pointers* (e#tor :6aseF ; .ush."a#k(neE 6ase); KL .ush."a#k(neE 2eri(ed); KL too cleanup* for ((e#tor :6aseF**iterator i 6 ."egin(); i 6 .end(); ++i) delete i;
Ge prolem Eit tis solution is tat after ouHre done Eit te container, ou need to manuall cleanup te o>ects stored in it. Gis is ot error prone and not e'ception safe. 8mart pointers are a possile solution, as illustrated eloE. (!n alternatie solution is a smart container, li?e te one implemented in pointainer..) (e#tor : linked.tr :6aseF F ; .ush."a#k(neE 6ase); KL .ush."a#k(neE 2eri(ed); KL too cleanup is automatic
8ince te smart pointer automaticall cleans up after itself, tere is no need to manuall delete te pointed o>ects. ote* 8G2 containers ma cop and delete teir elements eind te scenes (for e'ample, Een te resiAe temseles). Gerefore, all copies of an element must e euialent, or te Eron cop ma e te one to surie all tis copin and deletin. Gis means tat some smart pointers cannot e used Eitin 8G2
containers, specificall te standard autoYptr and an oEnersip-transferrin pointer. Mor more info aout tis issue, see #++ 4uru of te Oee? <.
!hi#h one should * use$ !re ou confused enou0 Oell, tis summar sould elp.
!hi#h3 Local variables Ge standard autoYptr is te simplest smart pointer, and it is also, Eell, standard. $f tere are no special reuirements, ou sould use it. Mor local ariales, it is usuall te rit coice.
!hi#h3 Class members !ltou ou can use autoYptr as a class memer (and sae ourself te troule of freein o>ects in te destructor), copin one o>ect to anoter Eill nullif te pointer, as illustrated JeloE. class 1yClass { auto.tr :intF p; ... }; 1yClass '; do some meaninful tins Eit ' 1yClass 6 '; '.p noE as a 22 pointer
sin a copied pointer instead of autoYptr soles tis prolem* te copied o>ect () ets a neE cop of te memer. ote tat usin a reference counted or reference lin?ed pointer means tat if canes te memer, tis cane Eill also affect ' Gerefore, if ou Eant to sae memor, ou sould use a #KO pointer and not a simple reference countedlin?ed pointer.
!hi#h3 STL containers !s e'plained aoe, usin arae-collected pointers Eit 8G2 containers lets ou store o>ects from different classes in te same container. $t is important to consider te caracteristics of te specific arae collection sceme used. 8pecificall, reference countinlin?in can lea? in te case of circular references (i.e., Een te pointed o>ect itself contains a counted pointer, Eic points to an o>ect tat contains te oriinal counted pointer). $ts adantae oer oter scemes is tat it is ot simple to implement and deterministic. Ge deterministic eaior ma e important in some real time sstems, Eere ou cannot alloE te sstem to suddenl Eait Eile te arae collector performs its ouse?eepin duties.
4enerall spea?in, tere are tEo Eas to implement reference countin* intrusie and non-intrusie. $ntrusie means tat te pointed o>ect itself contains te count. Gerefore, ou cannot use intrusie reference countin Eit 5-rd part classes tat do not alread ae tis feature. Nou can, oEeer, derie a neE class from te 5-rd part class and add te count to it. on-intrusie reference countin reuires an allocation of a count for eac counted o>ect. Ge countedYptr. is an e'ample of non-intrusie reference countin.
Heference lin"ing does not reuire any changes to be made to the pointed obects, nor does it reuire any additional allocations 0 reference lin"ed pointer ta"es a little more space than a reference counted pointer - ust enough to store one or two more pointers
Jot reference countin and reference lin?in reuire usin loc?s if te pointers are used more tan one tread of e'ecution.
!hi#h3 Explicit ownership transfer 8ometimes, ou Eant to receie a pointer as a function arument, ut ?eep te oEnersip of tis pointer (i.e. te control oer its lifetime) to ourself. Kne Ea to do tis is to use consistent namin-conentions for suc cases. GalientHs 4uide to Tesinin Wrorams recommends usin "adopt" to mar? tat a function adopts oEnersip of a pointer. sin an oEned pointer as te function arument is an e'plicit statement tat te function is ta?in oEnersip of te pointer.
!hi#h3 Big objects $f ou ae o>ects tat ta?e a lot of space, ou can sae some of tis space usin #KO pointers. Gis Ea, an o>ect Eill e copied onl Een necessar,
and sared oterEise. Ge sarin is implemented usin some arae collection sceme, li?e reference countin or lin?in.
Explicit ownership transfer Owned pointer Big objects
Copy on write
Con#lusion 8mart pointers are useful tools for Eritin safe and efficient code in #++. 2i?e an tool, te sould e used Eit appropriate care, tout and ?noElede. Mor a compreensie and in dept analsis of te issues concernin smart pointers, $ recommend readin !ndrei !le'andrescuHs capter aout smart pointers in is oo? Vodern #++ Tesin. Meel free to use m oEn smart pointers in our code, and do tell me if ou are ain an prolems Eit tem. Ge Joost #++ liraries include some smart pointers, Eic are more riorousl tested and actiel maintained. To tr tem first, if te are appropriate for our needs. Copyright 1999 by Yonat Sharon http3))ootipsorg)yonat)Ide)smart-pointershtml
This article was first published in #++ report in two parts, in the July/August 199 and !ecember 199 issues"
1emory 1anagement in C++ by Nathan C. Myers
#emory usage in $%% is as the sea come to land& a tide rolls in, and sweeps out again, lea'ing only puddles and stranded fish"
At inter'als, a wa'e crashes ashore( but the ripples never cease" *ntrodu#tion Van prorams ae little need for memor manaement; te use a fi'ed amount of memor, or simpl consume it until te e'it. Ge est tat can e done for suc prorams is to sta out of teir Ea. Kter prorams, includin most #++ prorams, are muc less deterministic, and teir performance can e profoundl affected te memor manaement polic te run under. nfortunatel, te memor manaement facilities proided man sstem endors ae failed to ?eep pace Eit roEt in proram siAe and dnamic memor usae. Jecause #++ code is naturall oraniAed class, a common response to tis failure is to oerload memer operator neE for indiidual classes. $n addition to ein tedious to implement and maintain, oEeer, tis piece-meal approac can actuall urt performance in lare sstems. Mor e'ample, applied to a tree-node class, it forces nodes of eac tree to sare paes Eit nodes of oter (proal unrelated) trees, rater tan Eit related data. Murtermore, it tends to frament memor ?eepin lare, mostl empt loc?s dedicated to eac class. Ge result can e a uic? neEdelete ccle tat accidentall causes irtual memor trasin. !t est, te approac interferes Eit sstem-Eide tunin efforts. Gus, Eile detailed ?noElede of te memor usae patterns of indiidual classes can e elpful, it is est applied tunin memor usae for a Eole proram or ma>or susstem. Ge first alf of tis article descries an interface Eic can ease suc tunin in #++ prorams. Jefore tunin a particular proram, oEeer, it pas to improe performance for all prorams, improin te loal memor manaer. Ge second alf of tis article coers te desin of a loal memor manaer tat is as fast and space-efficient as per-class allocators. Jut raE speed and efficienc are onl a einnin. ! memor manaement lirar Eritten in #++ can e an oraniAational tool in its oEn rit. Den as Ee confront te traditional prolems inolin lare data structures, proress in operatin sstems is ieldin different )inds of memor -- sared memor, memor-mapped files, persistent storae -- Eic must e manaed as Eell. Oit a common interface to all tpes of memor, most classes need not ?noE te difference. Gis ma?es uite a contrast Eit sstems of classes ard-Eired to use onl reular memor. Glo"al Oerator 7e& $n #++, te onl Ea to oraniAe memor manaement on a larer scale tan te class is oerloadin te loal operator neE. Go select a memor manaement polic reuires addin a placement argument , in tis case a reference to a class Eic implements te polic* e'tern oid operator neE(siAeYt, class Ieap&);
Oen Ee oerload te operator neE in tis Ea, Ee reconiAe tat te reular operator neE is implementin a polic of its oEn, and Ee Eould li?e to tune it as Eell. Gat is, it ma?es sense to offer te same coices for te reular operator neE as for te placement ersion.
$n fact, one cannot proide an interestin placement operator neE Eitout also replacin te reular operator neE. Ge loal operator delete can ta?e no user parameters, so it must e ale to tell Eat to do >ust loo?in at te memor ein freed. Gis means tat te operator delete and all operators neE must aree on a memor manaement arcitecture. Mor e'ample, if our loal operators neE Eere to e uilt on top of malloc(), Ee Eould need to store e'tra data in eac loc? so tat te loal operator delete Eould ?noE Eat to do Eit it. !ddin a Eord of oeread for eac o>ect to malloc()Hs oEn oeread (a total of 1= tes, on most R$8#s), Eould seem a craA Ea to improe memor manaement. Mortunatel, all tis space oeread can e eliminated passin malloc(), as Eill e seen later. Ge need to replace te loal operators neE and delete Een addin a placement operator neE as profound effects on memor manaement sstem desin. $t means tat it is impossile to interate different memor manaement arcitectures. Gerefore, te top-leel memor manaement arcitecture must e totall eneral, so tat it can support an polic Ee mit Eant to appl. Gotal eneralit, in turn, reuires asolute simplicit. An *nterfa#e IoE simple can Ee et0 2et us consider some declarations. Ieap is an astract class* class Ieap { protected* irtual SIeap(); pulic* irtual oid allocate(siAeYt) 6 3; static Ieap& EatIeap(oid); };
(Ge static memer function EatIeap(oid) is discussed later.) IeapHs astract interface is simple enou. 4ien a loal Ieap pointer, te reular loal operator neE can use it* e'tern Ieap YYloalYeap; inline oid operator neE(siAeYt sA) { return **YYloalYeap-Fallocate(sA); }
$nline dispatcin ma?es it fast. $tHs eneral too; Ee can use te Ieap interface to implement te placement operator neE, proidin access to an priate eap* inline oid operator neE(siAeYt siAe, Ieap& eap { return eap.allocate(siAe); }
Oat ?ind of implementations mit Ee define for te Ieap interface0 Kf course te first must e a eneral purpose memor allocator, class Ieap!n. (Ieap!n is te memor manaer descried in detail in te second alf of tis article.) Ge loal eap pointer, used te reular operator neE defined aoe, is initialiAed to refer to an instance of class Ieap!n* e'tern class Ieap!n YYGIDYloalYeap; Ieap YYloalYeap 6 &YYGIDYloalYeap;
sers, too, can instantiate class Ieap!n to ma?e a priate eap* Ieap!n& meap 6 neE Ieap!n;
and allocate storae from it, usin te placement operator neE* VGpe mine 6 neE(meap) VGpe;
!s promised, deletion is te same as alEas* delete mine;
oE Ee ae te asis for a memor manaement arcitecture. $t seems tat all Ee need to do is proide an appropriate implementation of class Ieap for an polic Ee mit Eant. !s usual, life is not so simple. Comli#ations Oat appens if VGpeHs constructor itself needs to allocate memor0 Gat memor sould come from te same eap, too. Oe could pass a eap reference to te constructor* mine 6 neE(meap) VGpe(meap);
and store it in te o>ect for use later, if needed. IoEeer, in practice tis approac leads to a massie proliferation of Ieap& aruments -- in constructors, in functions tat call constructors, eerEere -- Eic penetrates from te top of te sstem (Eere te eaps are manaed) to te ottom (Eere te are used). ltimatel, almost eer function needs a Ieap& arument. !pplied earnestl, te result can e orrendous. Den at est, suc an approac ma?es it difficult to interate oter liraries into a sstem. Kne Ea to reduce te proliferation of Ieap aruments is to proide a function to call to discoer Eat eap an o>ect is on. Gat is te purpose of te te Ieap**EatIeap() static memer function. Mor e'ample, ereHs a VGpe memer function tat allocates some uffer storae* car VGpe**ma?eYuffer() { Ieap& aIeap 6 Ieap**EatIeap(tis); return neE(aIeap) carJM8$Z/; }
($f "tis" points into te stac? or static space, EatIeap() returns a reference to te default loal eap.) !noter Ea to reduce Ieap arument proliferation is to sustitute a priate eap to e used te loal operator neE. 8uc a loal resource calls for inerl andlin. #lass Ieap8tac?GopHs constructor replaces te default eap Eit its arument, ut retains te old default so it can e restored te destructor* class Ieap8tac?Gop { Ieap oldY; pulic* Ieap8tac?Gop(Ieap& ); SIeap8tac?Gop(); };
Oe mit use tis as folloEs* { Ieap8tac?Gop top 6 meap; mine 6 neE VGpe; }
oE space for te VGpe o>ect, and an secondar store allocated its constructor, comes from meap. !t te closin rac?et, te destructor SIeap8tac?Gop() restores te preious default loal eap. $f one of VGpeHs memer functions mit later Eant to allocate more space from te same eap, it
can use EatIeap(); or te constructor can sae a pointer to te current loal eap efore returnin. #reatin a Ieap8tac?Gop o>ect is er clean Ea to install an loal memor manaement mecanism* a Ieap8tac?Gop o>ect created in main() uietl slips a neE memor allocator under te Eole proram. 8ome classes must allocate storae from te top-leel loal eap reardless of te current default. !n o>ect can force itself to e allocated tere definin a memer operator neE, and can control Eere its secondar storae comes from te same tecniues descried aoe. Oit Ieap8tac?Gop, man classes need not ?noE aout Ieap at all; tis can ma?e a i difference Een interatin liraries from arious sources. Kn te oter and, te meanin of Ieap**EatIeap() (or a Ieap& memer or arument) is easier to rasp; it is clearer, and terefore safer. Oile neiter approac is Eoll satisfactor, a careful mi' of te tEo can reduce te proliferation of Ieap& aruments to a reasonale leel. 8ses for Pri(ate %eas Jut Eat can priate eaps do for us0 Oe ae inted tat improed localit of reference leads to etter performance in a irtual memor enironment, and tat a uniform interface elps Een usin special tpes of memor. Kne oious use for priate eaps is as a sort of poor manHs arae collection* Ieap meap 6 neE IeapGras; ... lots of calls to neE(meap) delete meap;
$nstead of deletin o>ects, Ee discard te Eole data structure at one troE. Ge approac is sometimes called "lifetime manaement". 8ince te destructors are neer called, ou must carefull control Eat ?ind of o>ects are put in te eap; it Eould e aAardous eer to install suc a eap as te default (Eit Ieap8tac?Gop) ecause man classes, includin iostream, allocate space at unpredictale times. Tanlin pointers to o>ects in te deleted eap must e preented, Eic can e tric? if an o>ects secretl sare storae amon temseles. K>ects Eose destructors do more tan >ust delete oter o>ects reuire special andlin; te eap ma need to maintain a reistr of o>ects tat reuire "finaliAation". Jut priate eaps ae man oter uses tat donHt iolate #++ lanuae semantics. Weraps te uietest one is simpl to et etter performance tan our endorHs malloc() offers. $n man lare sstems, memer operator neE is defined for man classes >ust so te ma call te loal operator neE less often. Oen te loal operator neE is fast enou, suc code can e deleted, ieldin easier maintenance, often Eit a net ain in performance from etter localit and reduced framentation. !n idea tat stri?es man people is tat a priate eap could e Eritten tat is optimiAed to Eor? Eell Eit a particular aloritm. Jecause it need not field reuests from te rest of te proram, it can concentrate on te needs of tat aloritm. Ge simplest e'ample is a eap tat allocates o>ects of onl one siAe; as Ee Eill see later, oEeer, te default eap can e made fast enou tat tis is no reat adantae. ! mar?release mecanism is optimal in some conte'ts (suc as parsin), if it can e used for onl part of te associated data structure.
Oen sared memor is used for interprocess communication, it is usuall allocated te operatin sstem in loc?s larer tan te o>ects tat ou Eant to sare. Mor tis case a eap tat manaes a sared memor reion can offer te same enefits tat reular operator neE does for priate memor. $f te interface is te same as for non-sared memor, o>ects ma not need to ?noE te are in sared memor. 8imilarl, if ou are constrained to implement our sstem on an arcitecture Eit a tin address space, ou ma need to sEap memor sements in and out. $f a priate eap ?noEs oE to andle tese sements, o>ects tat donHt een ?noE aout sEappin can e allocated in tem. $n eneral, Eeneer a cun? of memor is to e cared up and made into arious o>ects, a Ieap-li?e interface is called for. $f tat interface is te same for te Eole sstem, ten oter o>ects need not ?noE Eere te cun? came from. !s a result, o>ects Eritten Eitout te particular use in mind ma safel e instantiated in er peculiar places. $n a multi-treaded proram, te loal operator neE must carefull e'clude oter treads Eile it operates on its data structures. Ge time spent >ust ettin and releasin te loc? can itself ecome a ottlenec? in some sstems. $f eac tread is ien a priate eap Eic maintains a cace of memor aailale Eitout loc?in, te treads need not sncroniAe e'cept Een te cace ecomes empt (or too full). Kf course, te operator delete must e ale to accept loc?s allocated an tread, ut it need not sncroniAe if te loc? ein freed came from te eap oEned te tread tat is releasin it. ! eap tat rememers details aout oE, or Een, o>ects in it Eere created can e er useful Een implementin an o>ect- oriented dataase or remote procedure call mecanism. ! eap tat sereates small o>ects tpe can alloE tem to simulate irtual function eaior Eitout te oeread of a irtual function tale pointer in eac o>ect. ! eap tat Aero-fills loc?s on allocation can simplif constructors. Wrorams can e instrumented to collect statistics aout memor usae (or lea?ae) sustitutin a specialiAed eap at arious places in a proram. se of priate eaps alloEs muc finer ranularit tan te traditional approac of sadoEin malloc() at lin? time. $n te remainder of tis article Ee Eill e'plore oE to implement Ieap!n efficientl, so tat malloc(), te loal operator neE(siAeYt), te loal operator neE(siAeYt, Ieap&), and Ieap**EatIeap(oid) can e uilt on it. A 1emory 1anager in C++ !n optimal memor manaer as minimal oeread* space used is ut fractionall larer tan te total reuested, and te neEdelete ccle time is small and constant. Van factors Eor? aainst aciein tis optimum. $n man endor liraries, memor used te memor manaer itself, for oo??eepin, can doule te total space used. Mramentation, Eere loc?s are free ut unaailale, can also multipl te space used. 8pace matters, een toda, ecause irtual memor pae faults sloE doEn our proram (indeed, our entire computer), and sEap space limits can e e'ceeded >ust as can real memor.
! memor manaer can also Easte time in man Eas. Kn allocation, a loc? of te rit siAe must e found or made. $f made, te remainder of te split loc? must e placed Eere it can e found. Kn deallocation, te freed loc? ma need to e coalesced Eit an neiorin loc?s, and te result must e placed Eere it can e found aain. 8stem calls to otain raE memor can ta?e loner tan an oter sinle operation; a pae fault tat results Een idle memor is touced is >ust a idden sstem call. !ll tese operations ta?e time, time spent not computin results. Ge effects of Easteful memor manaement can e ard to see. Gime spent trasin te sEap file doesnHt soE up on profiler output, and is ard to attriute to te responsile code. Kften te prolem is easil isile onl Een memor usae e'ceeds aailale sEap space. Va?e no mista?e* poor memor manaement can multipl our proramHs runnin time, or so o doEn a macine tat little else can run. Jefore uin (or ma?in our customers u) more memor, it ma?es sense to see Eat can e done Eit a little code. Prin#iles ! memor manaer pro>ect is an opportunit to appl principles of ood desin* 8eparate te common case from special cases, and ma?e te common case fast and ceap, and oter cases tolerale; ma?e te user of a feature ear te cost of its use; use ints; reuse ood ideas. 2ampson/ Jefore delin into detailed desin, Ee must e clear aout our oals. Oe Eant a memor manaer tat satisfies te folloEin* J Speed3 !t must be much faster than e(isting memory managers, especially for small obects .erformance should not suffer under common usage patterns, such as repeatedly allocating and freeing the same bloc" J Eow oerhead3 he total sie of headers and other wasted space must be a small percentage of total space used, een when all obects are tiny Hepeated allocation and deallocation of different sies must not cause memory usage to grow without bound J Small wor"ing set3 he number of pages touched by the memory manager in satisfying a reuest must be minimal, to aoid paging delays in irtual memory systems nused memory must be returned to the operating system periodically J Hobustness3 @rroneous programs must hae difficulty corrupting the memory manager's data structures @rrors must be flagged as soon as possible, not allowed to acc umulate Out-of-memory eents must be handled gracefully J .ortability3 he memory manager must adapt easily to different machines J Conenience3 sers mustn't need to change code to use it
J le(ibility3 !t must be easily customied for unusual needs, without imposing any additional oerhead e#hniques Kptimal memor manaers Eould e common if te Eere easil uilt. Ge are scarce, so ou can e'pect tat a ariet of sutle tecniues are needed een to approac te optimum. Kne suc tecniue is to treat different reuest siAes differentl. $n most prorams, small loc?s are reuested oerEelminl more often tan lare loc?s, so ot time and space oeread for tem is felt disproportionatel. !noter tecniue results from notin tat tere are onl a feE different siAes possile for er small loc?s, so tat eac suc siAe ma e andled separatel. Oe can een afford to ?eep a ector of free loc? lists for tose feE siAes. ! tird is to aoid sstem call oeread reuestin memor from te operatin sstem in i cun?s, and not toucin unused (and possil paed-out) loc?s unnecessaril. Gis means data structures consulted to find a loc? to allocate sould e stored compactl, apart from te unused loc?s te descrie. Ge final, and most important, tecniue is to e'ploit address aritmetic Eic, Eile not strictl portale accordin to lanuae standards, Eor?s Eell on all modern flat-memor arcitectures. ! pointer alue can e treated as an inteer, and itEise loical operations ma e used on it to ield a neE pointer alue. $n particular, te loE its ma e mas?ed off to ield a pointer to a eader structure tat descries te loc? pointed to. $n tis Ea a loc? need not contain a pointer to tat information. Murtermore, man loc?s can sare te same eader, amortiAin its oeread across all. (Gis tecniue is familiar in te 2$8W communit, Eere it is ?noEn as "pae-tain".) Oit so man oals, principles, and tecniues to ?eep trac? of, it sould e no surprise tat tere are plent of pitfalls to aoid. Ge Eill e discussed later. A 2esign Ge first ma>or feature of te desin is suested te final tEo tecniues aoe. Oe reuest memor from te operatin sstem in units of a lare poEer of tEo (e.. =9L tes) in siAe, and place tem so te are alined on suc a oundar. Oe call tese units "sements". !n address Eitin te sement ma ae its loE its mas?ed off, ieldin a pointer to te sement eader. Oe can treat tis eader as an instance of te astract class Ieap8ement* class Ieap8ement { pulic* irtual oid free(oid) 6 3; irtual oid realloc(oid) 6 3; irtual Ieap& oEnedY(oid) 6 3; };
Ge second ma>or feature of te desin ta?es adantae of te small numer of small-loc? siAes possile. ! sement (Eit a eader of class IeapWaese) is split up into paes, Eere eac pae contains loc?s of onl one siAe. ! ector of free lists, Eit one element for eac siAe, alloEs instant access to a free loc? of te rit siAe. Teallocation is >ust as uic?; no coalescin is needed. Dac pae
as >ust one eader to record te siAe of te loc?s it contains, and te oEnin eap. Ge pae eader is found address aritmetic, >ust li?e te sement eader. $n tis Ea, space oeread is limited to a feE percent, een for te smallest loc?s, and te time to allocate and deallocate te pae is amortiAed oer all usae of te loc?s in te pae. Mor larer loc?s, tere are too man siAes to ie eac a sement; ut suc loc?s ma e pac?ed ad>acent to one anoter Eitin a sement, to e coalesced Eit neiorin free loc?s Een freed. (Oe Eill call suc loc?s "spans", Eit a sement eader of tpe Ieap8panse.) Mramentation, te proliferation of free loc?s too small to use, is te cief daner in span sements, and tere are seeral Eas to limit it. Jecause te common case, small loc?s, is andled separatel, Ee ae some reatin room* spans ma ae a lare ranularit, and Ee can afford to spend more time manain tem. ! alanced tree of aailale siAes is fast enou tat Ee can use seeral searces to aoid creatin tin unusale spans. Ge tree can e stored compactl, apart from te free spans, to aoid toucin tem until te are actuall used. Minall, aressie coalescin elps reclaim small loc?s and ?eep lare loc?s aailale. Jloc?s too i to fit in a sement are allocated as a contiuous seuence of sements; te eader of te first sement in te seuence is of class IeapIuese. Vemor Easted in te last sement is muc less tan mit e feared; an paes not touced are not een assined te operatin sstem, so te aerae Easte for ue loc?s is onl alf a irtual-memor pae. Tispatcin for deallocation is simple and uic?* oid operator delete(oid ptr) { lon eader 6 (lon)ptr & V!8L; ((Ieap8ement)eader)-Ffree(ptr); }
Ieap8ement**free() is a irtual function, so eac sement tpe andles deallocation its oEn Ea. Gis alloEs different Ieaps to coe'ist. $f te freed pointer does not point to allocated memor, te proram Eill most li?el cras immediatel. (Gis is a feature. Jus tat are alloEed to accumulate are e'tremel difficult to trac? doEn.) Ge classical # memor manaement functions, malloc(), calloc(), realloc(), and free() can e implemented on top of Ieap!n >ust as Eas te loal operator neE. Knl realloc() reuires particular support. Ge onl remainin feature to implement is te function Ieap**EatIeap(oid ptr). Oe cannot assume tat ptr refers to eap storae; it ma point into te stac?, or static storae, or elseEere. Ge solution is to ?eep a itmap of allocated sements, one it per sement. Kn most arcitectures tis ta?es L Eords to coer te entire address space. $f te pointer refers to a manaed sement, Ieap8ement**oEnedY() reports te oEnin eap; if not, a reference to te default loal eap ma e returned instead. ($n te 2$8W communit, tis tecniue is referred to as JJKW, or "i a oH paes".) Pitfalls