50 Chapter 4 Memory Managemen t In Ja v a the task of - - PDF document

50 chapter 4 memory managemen t in ja v a the task of
SMART_READER_LITE
LIVE PREVIEW

50 Chapter 4 Memory Managemen t In Ja v a the task of - - PDF document

50 Chapter 4 Memory Managemen t In Ja v a the task of memory managemen t is largely conducted in the bac kground, just b e- y ond the issues of concern to the t ypical programmer. This b e an adv an tage,


slide-1
SLIDE 1 50
slide-2
SLIDE 2 Chapter 4 Memory Managemen t In Ja v a the task
  • f
memory managemen t is largely conducted in the bac kground, just b e- y
  • nd
the issues
  • f
concern to the t ypical programmer. This c an b e an adv an tage, as it remo v es a complex task from the programmers range
  • f
vision, th us allo wing him
  • r
her to concen trate
  • n
more application sp ecic details. On the
  • ther
hand, it also means that the Ja v a programmer has little con trol
  • v
er ho w memory managemen t is p erformed. Using C ++ , in con trast, memory managemen t is explicitly under the direction
  • f
the W arning The C ++ pr
  • gr
ammer must always b e awar e
  • f
how mem-
  • ry
manage- ment is b eing p erforme d programmer. If prop erly used this can w
  • rk
to the programmers adv an tage, p ermitting m uc h more ecien t use
  • f
memory than is p
  • ssible
with Ja v a. But if improp erly used (or, more
  • ften,
ignored) memory managemen t issues can bloat a program at run-time,
  • r
mak e a program v ery inecien t. F
  • r
this reason, to write eectiv e C ++ programs it is imp
  • rtan
t to understand ho w the memory managemen t system
  • p
erates. Because in C ++ the programmer is resp
  • nsible
for memory managemen t, there are a v ariet y
  • f
errors that are p
  • ssible
in C ++ programs but are rare
  • r
un usual in Ja v a. These include the follo wing:
  • Using
a v alue b efore it has b een initialized. (The Ja v a language requires a datao w analysis that will detect man y
  • f
these errors. The C ++ language mak es no suc h W arning C ++ do es not p erform dataow analysis to dete ct p
  • tential
ly un- dene d lo c al variables requiremen t).
  • Allo
cating memory for a v alue, then not deleting it
  • nce
it is no longer b eing used. (This will cause a long running program to consume more and more memory , un til it fails in a catastrophic fashion.)
  • Using
a v alue after it has b een freed. (Once returned to the memory managemen t system, the con ten ts
  • f
a freed lo cation are t ypically
  • v
erwritten in an unpredictable fashion. Th us, the con ten ts
  • f
a freed v alue will b e unpredictable.) Eac h
  • f
these p
  • ten
tial errors will b e illustrated b y examples in the remainder
  • f
this c hapter. 51
slide-3
SLIDE 3 52 CHAPTER 4. MEMOR Y MANA GEMENT 4.1 The Memory Mo del T
  • understand
ho w memory managemen t is p erformed in C ++ it is rst necessary to appre- ciate the C ++ memory mo del, whic h diers in a fundamen tal fashion from the Ja v a memory mo del. In man y w a ys, the C ++ mo del is m uc h closer to the actual mac hine represen tation than is the Ja v a memory mo del. This closeness p ermits an ecien t implemen tation, at the exp ense
  • f
needing increased diligence
  • n
the part
  • f
the programmer. In C ++ there is a clear distinction b et w een memory v alues that are stack-r esident, and Define Stack- r esident val- ues ar e cr e ate d when a pr
  • c
e dur e is enter e d, and deletete d when the pr
  • c
e dur e exits those that are he ap-r esident. Stac k residen t v alues are those created automatically when a pro cedure is en tered
  • r
exited, while heap residen t v alues m ust b e explicitly created using the new
  • p
erator. In the follo wing sections w e will describ e some
  • f
the c haracteristics
  • f
b
  • th
  • f
these, and the problems the programmer should lo
  • k
  • ut
for. 4.2 Stac k Residen t Memory V alues Both the stac k and the heap are in ternal data structures managed b y a run-time system. Note A n acti- vation r e c
  • r
d is sometimes c al le d an activation fr ame,
  • r
a stack fr ame Of the t w
  • ,
the stac k is m uc h more
  • rderly
. V alues
  • n
a stac k are strongly tied to pro cedure en try and exit. When a pro cedure b egins execution, a new section
  • f
the stac k is created. This stac k segmen t holds parameters, the return address for the caller, sa v ed in ternal reg- isters and
  • ther
mac hine sp ecic information, and space for lo cal v ariables. The section
  • f
a stac k sp ecically dev
  • ted
to
  • ne
pro cedure is
  • ften
termed an activation r e c
  • r
d. In Ja v a,
  • nly
primitiv e v alues are truly stac k residen t. Ob jects and arra ys are alw a ys allo cated
  • n
the heap. Compare the follo wing t w
  • example
pro cedures. Eac h creates a lo cal in teger, a lo cal arra y , and an
  • b
ject instance. void test () // Ja v a f int i; int a[ ] = new int[10]; anObject ao = new anObject(); ... g void test () // C++ f int i; int a[10]; anObject ao; ... g
slide-4
SLIDE 4 4.2. ST A CK RESIDENT MEMOR Y V ALUES 53 In the Ja v a pro cedure
  • nly
the primitiv e in teger v alue is actually allo cated space
  • n
the stac k b y the declaration. Both the arra y and the
  • b
ject v alue m ust b e explicitly created (as heap-residen t v alues) using the new
  • p
erator. In C ++ ,
  • n
the
  • ther
hand, all three v alues will reside
  • n
the stac k, and none require an y actions b ey
  • nd
the declaration to bring them in to existence. Pro cedure in v
  • cations
execute in a v ery
  • rderly
fashion. If pro cedure A in v
  • k
es pro ce- dure B, and B in turn in v
  • k
es C, then pro cedure C m ust terminate b efore B will con tin ue with execution, and B in turn m ust terminate b efore A will resume. This prop ert y allo ws activ ation records to b e managed in a v ery ecien t and
  • rderly
manner. When a pro cedure is called, an activ ation record is created and pushed
  • n
the stac k, and when the pro cedure returns, the activ ation record can b e p
  • pp
ed from the stac k. A p
  • in
ter can b e used to p
  • in
t to the curren t top
  • f
stac k. Allo cation
  • f
a section
  • f
the stac k then simply means mo ving this p
  • in
ter v alue forw ard b y the required amoun t. The eciencies
  • f
stac k memory are not without cost. There are t w
  • ma
jor dra wbac ks to the use
  • f
the stac k for v ariable storage:
  • The
lifetime
  • f
stac k residen t memory v alues is tied to pro cedure en try and exit. This Define The lifetime is the p erio d
  • f
time a value c an b e use d means that stac k residen t v alues cease to exist when a pro cedure returns. An attempt to use a stac k residen t v alue after it has b een deleted will t ypically result in error.
  • The
size
  • f
stac k residen t memory v alues m ust b e kno wn at compile time, whic h is when the structure
  • f
the activ ation record is laid
  • ut.
The follo wing sections will describ e some
  • f
the implications
  • f
these t w
  • issues.
4.2.1 Lifetime errors An imp
  • rtan
t fact to remem b er is that
  • nce
a pro cedure returns from execution, an y stac k residen t v alues are deleted and no longer accessible. A r efer enc e to suc h a v alue (see Chap- ter 3) will no longer b e v alid, although it ma y for a time app ear to w
  • rk.
Here are some examples. // W ARNING { Program con tains an error char
  • readALine
() f char buffer[1000]; // declare a buer for the line gets(buffer); // read the line return buffer; // return text
  • f
line g
slide-5
SLIDE 5 54 CHAPTER 4. MEMOR Y MANA GEMENT In this example the pro cedure will return a p
  • in
ter to the arra y buer, 1 ho w ev er the memory for the buer will ha v e b een deleted as part
  • f
the pro cedure return. The p
  • in
ter will reference v alues that ma y
  • r
ma y not b e correct, and will almost certainly b e
  • v
erwritten
  • nce
the next pro cedure is called. Con trast this with an equiv alen t Ja v a pro cedure: String readALine (BufferedInput inp) throws IOException f // create a buer for the line String line = inp.readLine(); return line; g Although the v ariable line is declared inside the pro cedure, the value assigned to the v ariable will b e heap-residen t. Therefore this v alue will con tin ue to exist, ev en after the pro cedure returns. F unction return v alues are b y no means the
  • nly
w a y to create dangling references. An assignmen t to a global v ariable
  • r
a b y-reference parameter can do the same thing, as sho wn in the follo wing: char
  • lineBuffer;
// global declaration
  • f
p
  • in
ter to buer // W ARNING { Program con tains an error void readALine () f char buffer[1000]; // declare a buer for the line gets(buffer); // read the line lineBuffer = buffer; // set p
  • in
ter to reference buer g Some
  • f
the more sophisticated C ++ compilers will w arn ab
  • ut
suc h errors, but the programmer should not dep end up
  • n
this b eing caugh t. 4.2.2 Size errors { the Slicing Problem F
  • r
  • b
ject-orien ted programming,
  • ne
  • f
the most sev ere restrictions
  • f
stac k-based memory managemen t deriv es from the fact that the p
  • sitions
  • f
v alues within the activ ation record are determined at compile time. F
  • r
primitiv e v alues and p
  • in
ters this is a small concern. 1 The close relationship in C ++ b et w een arra ys and p
  • in
ters is discussed in detail in Chapter 3. It should also b e noted that gets is a problematic function, for man y
  • f
the reasons cited in this c hapter. Better solutions to this problem are pro vided b y the Stream I/O pac k age describ ed in Chapter 10. Ho w ev er, gets is part
  • f
the legacy C ++ inherits from C, and is still commonly found in man y programs.
slide-6
SLIDE 6 4.2. ST A CK RESIDENT MEMOR Y V ALUES 55 Ho w ev er, it is an issue for arra ys and for
  • b
jects. F
  • r
arra ys, it means that the arra y b
  • und
m ust b e kno wn at compile time. F
  • r
  • b
jects, it means a limitation
  • n
the degree to whic h v alues can b e p
  • lymorphic.
Arra y Allo cations Stac k residen t arra ys m ust ha v e a size that is kno wn at compile time. Often programmers Note The size
  • f
any value stor e d
  • n
the stack must b e known at c
  • mpile
time a v
  • id
this problem b y allo cating an arra y with a size that is purp
  • sely
to
  • large.
An earlier example, whic h w e will rep eat, illustrated this tec hnique. Here the programmer is reading lines
  • f
input from a le, and has allo cated the c haracter arra y to hold 200 elemen ts,
  • n
the assumption that no line will ha v e an y more than this n um b er
  • f
c haracters. // W ARNING { Program con tains an error char buffer[200]; // making arra y global a v
  • ids
deletion error char
  • readALine
() f gets(buffer); // read the line return buffer; g P
  • ten
tial problems
  • ccur
since arra y b
  • unds
are not c hec k ed in C ++ at run time 2 . Should R ule Never assume that just b e- c ause an ar- r ay is big, it wil l always b e \big enough" an
  • v
erly-long line b e encoun tered in the le, the buer will simply b e exceeded, and the v alues read will
  • w
  • v
er in to whatev er happ ens to follo w the arra y in the activ ation record. This will ha v e the eect
  • f
c hanging the v alues
  • f
  • ther
v ariables in an unpredictable fashion, with generally infelicitous results. It is p
  • ssible
to create arra ys with sizes determined at run-time using heap-residen t v alues. This is done in a fashion similar to Ja v a, with the exception that the programmer m ust explicitly free the memory when no longer required (see Section 4.3). char
  • buffer;
int newSize; ... // newSize is giv en some v alue buffer = new Char[newSize]; // create an arra y
  • f
the giv en size ... delete [ ] buffer; // delete buer when no longer b eing used
slide-7
SLIDE 7 56 CHAPTER 4. MEMOR Y MANA GEMENT class A f public: // constructor A () : dataOne(2) f g // iden tication metho d virtual void whoAmI () f printf("class A"); g private: int dataOne; g; class B : public A f public: // constructor B () : dataTwo(4) f g // iden tication metho d virtual void whoAmI () f printf("class B"); g private: int dataTwo; g; Figure 4.1: A Class Hierarc h y for Illustrating the Slicing Problem
slide-8
SLIDE 8 4.2. ST A CK RESIDENT MEMOR Y V ALUES 57 The Slicing Problem Ja v a programmers are used to
  • b
ject v alues b eing p
  • lymorphic
(see Chapter 6). That is, a v ariable declared as main taining a v alue
  • f
  • ne
class can, in fact, b e holding a v alue deriv ed from a c hild class. In the class hierarc h y sho wn in Figure 4.1, 3 class A is extended b y a new class B, whic h
  • v
errides the virtual metho d whoAmI. 4 In b
  • th
Ja v a and C ++ it is legal to assign a v alue deriv ed from class B to a v ariable declared as holding an instance
  • f
class A: A instanceOfA; // declare instances
  • f
B instanceOfB; // class A and B instanceOfA = instanceOfB; instaceOfA.whoAmI () ; // question: what will happ en? Ho w ev er, the eect
  • f
this assignmen t will dier in the t w
  • languages.
The Ja v a pro- grammer will exp ect that, while the declaration
  • f
instanceOfA is class A, the v alue will con tin ue to b e that
  • f
a B, and th us the metho d in v
  • k
ed will b e that found in class B. This p
  • lymorphic
b eha vior runs in to conict with the stac k based memory allo cation R ule Static variables ar e never p
  • lymorphic
mo del. Note that v alues
  • f
class B are larger than v alues
  • f
class A, since they include an additional data eld (namely , the inherited eld dataOne, and the eld dataTw
  • dened
in class B). In
  • rder
to main tain the eciencies
  • f
the stac k-based memory allo cation, these additional elds are simply sliced a w a y when the assignmen t
  • ccurs.
Th us, the v alue ceases to b e an instance
  • f
class B, and simply b ecomes an instance
  • f
class A: A B
  • @
@
  • @
@ In this ligh t, it is therefore not surprising that the metho d executed b y the in v
  • cation
  • f
whoAmI will b e that
  • f
class A, and not that
  • f
class B. This is true regardless
  • f
whether the metho d whoAmI w as declared virtual. 2 See Chapter 3 for a further discussion
  • n
this issue. Note that there is an alternativ e function, fgets, that p ermits the buer size to b e sp ecied. As a general matter, fgets should b e preferred
  • v
er gets for just this reason. Ho w ev er, the t yp e
  • f
error discussed here arizes in man y situations, so the p
  • in
t is still v alid. 3 Output is here pro duced using the statemen t p rintf, whic h is
  • ne
  • f
t w
  • utput
tec hniques commonly encoun tered in C ++ programs. The topic if I/O libraries will b e discussed in Chapter 10. 4 See Chapter 6 for a more complete discussion
  • f
the k eyw
  • rd
virtual.
slide-9
SLIDE 9 58 CHAPTER 4. MEMOR Y MANA GEMENT Note carefully , ho w ev er, that slicing do es not
  • ccur
with references
  • r
with p
  • in
ters: W arning The message p assing rules for p
  • int-
ers and r efer- enes ar e dif- fer ent fr
  • m
those for sim- ple variables A & referenceToA = instanceOfB; referenceToA.whoA mI (); // will prin t class B B
  • pointerToB
= new B(); A
  • pointerToA
= pointerToB(); pointerToA->whoAm I( ); // will prin t class B Slicing
  • nly
  • ccurs
with
  • b
jects that are stac k residen t. F
  • r
this reason, man y C ++ programs mak e the ma jorit y
  • f
their
  • b
jects heap residen t. The issues the Ja v a programmer learning C ++ should b e a w are
  • f
when using heap allo cation are discussed in detail in the next section. 4.3 Heap Residen t Memory V alues Heap residen t v alues are created using the new
  • p
erator. Memory for suc h v alues resides
  • n
the he ap,
  • r
fr e e stor e, whic h is a separate part
  • f
memory from the stac k. T ypically suc h v alues are accessed through a p
  • in
ter, whic h will
  • ften
reside
  • n
the stac k. The follo wing con trasting co de fragmen ts in C ++ and Ja v a will illustrate this: Note The p ar enthe- sis ar e
  • mit-
te d fr
  • m
a new state- ment if ther e ar e no ar gu- ments for the c
  • nstructor
void test () // Ja v a f A anA = new A(); ... g void test () // C++ f A
  • anA
= new A; // note p
  • in
ter declaration if (anA == 0) ... // handle no memory situation ... delete anA; g Here anA will reside
  • n
the stac k (in b
  • th
Ja v a and C ++ ) but the v alue it references will reside
  • n
the heap:
slide-10
SLIDE 10 4.3. HEAP RESIDENT MEMOR Y V ALUES 59 The Stack " anA
  • *
The Heap ' & $ % Curren t Activ ation Record The Ja v a language hides the use
  • f
this p
  • in
ter v alue, and programmers seldom need b e concerned with it. In C ++ ,
  • n
the
  • ther
hand, the p
  • in
ter declaration is explicitly stated. In Ja v a if a memory request cannot b e satised an OutOfMemmo ry exception is thro wn. W arning Not al l c
  • m-
pilers wil l thr
  • w
an ex- c eption when mem-
  • ry
b e c
  • mes
exhauste d New er v ersions
  • f
C ++ will lik ewise thro w a bad allo c exception. Ho w ev er, earlier v ersions
  • f
the language w
  • uld
simply return a n ull p
  • in
ter v alue when a request could not b e satised. It is therefore imp
  • rtan
t to test for this condition, and tak e appropriate action (suc h as thro wing an exception y
  • urself
) if it
  • ccurs.
A more imp
  • rtan
t dierence relates to the reco v ery
  • f
heap based memory . Ja v a incor- Define A garb age c
  • l-
le ction sys- tem se ar ches
  • ut
and r e c
  • vers
unuse d mem-
  • ry
p
  • rates
garb age c
  • l
le ction in to its run-time library . The garbage collection system monitors the use
  • f
dynamically allo cated v ariables, and will automatically reco v er and reuse memory that is no longer b eing accessed. C ++ ,
  • n
the
  • ther
hand, lea v es this task to the programmer. Dynamically allo cated memory m ust b e handed bac k to the heap manager using the delete
  • p
erator. There are t w
  • forms
  • f
this
  • p
erator, b
  • th
  • f
whic h ha v e b een used in examples presen ted earlier in this c hapter. The deletion
  • f
an individual
  • b
ject is p erformed b y simply naming the p
  • in
ter v ariable, as in the example sho wn ab
  • v
e. When deleting an arra y a pair
  • f
empt y square braces m ust b e used. An example sho wing this syn tax w as presen ted earlier in Section 4.2.2. Because memory reco v ery m ust b e an explicit concern
  • f
the programmer, four t yp es
  • f
errors are common:
  • F
  • rgetting
to allo cate a heap-residen t v alue, and using a p
  • in
ter as if it w ere referencing a legitimate v alue.
  • F
  • rgetting
to hand un used memory bac k to the heap manager.
  • A
ttempting to use memory v alues after they ha v e b een handed bac k to the heap manager.
  • In
v
  • king
the delete statemen t
  • n
the same v alue more than
  • nce,
thereb y passing the same memory v alue bac k to the heap manager.
slide-11
SLIDE 11 60 CHAPTER 4. MEMOR Y MANA GEMENT In Ja v a the rst t yp e
  • f
error, if not caugh t b y the compiler, will generally raise a n ull W arning Uninitial- ize d values in C ++ ar e not
  • nly
not r e- p
  • rte
d by the c
  • mpiler,
but their initial values ar e gener al ly garb age p
  • in
ter exception. C ++ compilers are not
  • bligated
to try and detect the use
  • f
v ariables b efore they ha v e b een set, and few will. F urthermore, the initial con ten ts
  • f
memory are generally not determined. Th us, an uninitialized p
  • in
ter v alue will sometimes con tain a legal memory address ev en b efore it has b een set, although there is no w a y to kno w where in memory it is p
  • in
ting to. A ttempting to read from suc h a v alue
  • r
assigning to it will cause an unpredictable result. The second t yp e
  • f
error is termed a memory le ak. Often suc h leaks can
  • ccur
without Define A memory le ak is an al lo c a- tion
  • f
mem-
  • ry
that is never r e c
  • ver
e d an y harmful eects. Ho w ev er, in a long running program
  • r
if memory allo cation
  • ccurs
in a situation that is executed rep eatedly , suc h leaks will cause the memory requiremen ts for the program to increase
  • v
er time. Ev en tually the heap manager will b e unable to service a request for further memory , and the program will halt. Leaks are
  • ften
the result
  • f
successiv e assignmen ts to the same p
  • in
ter v ariable: AnObject
  • a;
... a = new AnObject(); ... a = new AnObject(); // leak,
  • ld
reference is no w lost The third t yp e
  • f
error sometimes
  • ccurs
as the result
  • f
an
  • v
er-zealous attempt to a v
  • id
the second error. Here memory is passed bac k to the heap manger b efore all references to the v alue ha v e b een deleted. As part
  • f
managing and recycling heap residen t v alues, the heap manager
  • ften
stores p ertinen t information in the v alue. F
  • r
example, the heap manager ma y k eep a list
  • f
similarly sized blo c ks
  • f
memory , and store in eac h blo c k a p
  • in
ter to the next elemen t. Th us, after a v alue is deleted the con ten ts are
  • ften
  • v
erwritten. Reading from suc h a v alue will pro duce garbage, and writing to suc h a v alue will confound the heap manager. Both errors are t ypically catastrophic. Dep ending up
  • n
the sophistication
  • f
the memory manager, the fourth error ma y
  • r
ma y not b e sev ere. Some heap mangers can detect this condition. Other heap mangers will not notice the error, but the in ternal data structures used b y the heap manager will b e put in to an inconsisten t state. This, to
  • ,
can result in unpredicatable errors. A simple rule
  • f
th um b is that ev ery time the new
  • p
erator is used, the programmer R ule A l- ways match memory al- lo c ations and deletions should b e able to iden tify where and under what circumstances the asso ciated delete directiv e will b e issued. There are t w
  • tec
hniques that are frequen tly used to help simplify the managemen t
  • f
heap v alues. These are:
  • Hide
the allo cation and release
  • f
dynamic memory v alues inside an
  • b
ject. The
  • b
ject is therefore the \o wner"
  • f
the heap residen t v alue, and is \resp
  • nsible"
for memory managemen t. F
  • r
example, the memory managemen t is
  • ften
tied to the lifetime
  • f
the
  • b
ject, whic h can sometimes b e more reliably predicted (for example, the
  • b
ject
slide-12
SLIDE 12 4.3. HEAP RESIDENT MEMOR Y V ALUES 61 is stac k residen t). This tec hnique is
  • nly
applicable where there is
  • nly
  • ne
p
  • in
ter to the heap residen t v alue.
  • If
it is not p
  • ssible
to designate a single \o wner" for a heap residen t v alue, then it is dicult to kno w who should b e resp
  • nsible
for deleting the v alue
  • nce
it is no longer b eing referenced. This problem can b e solv ed b y main taining, as part
  • f
the heap, a r efer enc e c
  • unt
that indicates the n um b er
  • f
p
  • in
ters to the v alue. When this coun t is decremen ted to zero, the v alue can b e reco v ered. W e will illustrate eac h
  • f
these tec hniques b y dev eloping a data abstraction for the String data t yp e. 4.3.1 Encapsulating Memory Managemen t String literals in C ++ , unlik e Ja v a, are v ery lo w lev el abstractions. A string literal in C ++ is treated as an arra y
  • f
c haracter v alues, and the
  • nly
p ermitted
  • p
erations are those com- mon to all arra ys. The String data t yp e in Ja v a is designed to pro vide a higher lev el
  • f
abstraction. A v ersion
  • f
this data structure is pro vided in the new Standard T emplate Library (the STL, see Chapter 9). It is also a common example found in man y in tro- ductory C ++ texts. The v ersion w e presen t here is sk eletal, describing
  • nly
those features related to memory managemen t. More complete implemen tations can b e found describ ed in [Budd 98a , Budd 94 , Lippman 91 , Coplien 92 ]. The class description for String is sho wn in Figure 4.2. As is common in C ++ , the shorter metho ds (in this case, all but
  • ne
metho d) are pro vided using in-line denitions in the class heading, while longer metho ds are found in an implemen tation le,
  • utside
the class denition. String v ariables can b e declared with no initialization,
  • r
initialized using either a literal string text, a c haracter arra y (that is, a p
  • in
ter to a c haracter)
  • r
another string v alue: string a; string b = "abc"; string c = b; The imp
  • rtan
t feature
  • f
this string abstraction is that there is a
  • ne-to-one
matc hing Note One way to man- age dy- namic al ly al- lo c ate d mem-
  • ry
is to make an
  • bje
ct r esp
  • n-
sible for managing the memory
  • f
String
  • b
jects to dynamically allo cated buers. Ev ery string has
  • ne
buer, and ev ery buer is \o wned" b y a sp ecic String. This buer is created b y the metho d resize: void String::resize(in t size) f if (buffer == 0) // no previous allo cation buffer = new char[1 + size]; else if (size > strlen(buffer)) f
slide-13
SLIDE 13 62 CHAPTER 4. MEMOR Y MANA GEMENT class String f public: // constructors String () : buffer(0) f g String (const char
  • right)
: buffer(0) f resize(strlen(ri gh t)) ; strcpy(buffer, right); g String (const String & right) : buffer(0) f resize(strlen(ri gh t.b uf fe r)) ; strcpy(buffer, right.buffer); g // destructor String () f delete [ ] buffer; g // assignmen t void
  • perator
= (const String & right) f resize(strlen(ri gh t.b uf fe r)) ; strcpy(buffer, right.buffer); g private: void resize (int size); char
  • buffer;
g; Figure 4.2: The Class String (V ersion One)
slide-14
SLIDE 14 4.3. HEAP RESIDENT MEMOR Y V ALUES 63 delete [ ] buffer; // reco v er
  • ld
v alue buffer = new char[1 + size]; g g If no buer has y et b een allo cated a buer
  • f
the requested size is created. (The
  • ne
extra c haracter is for the n ull c haracter inserted at the end
  • f
a string b y the function strcp y. Otherwise, if the curren t buer is to
  • small
for the requested n um b er
  • f
c haracters, then the curren t buer is returned to the heap manager, and a new buer is created. A string v ariable can b e assigned a v alue from another string v ariable: a = b; In this case, a c
  • py
  • f
the con ten ts
  • f
the righ t hand side is created: b a c
  • py
  • f
buer buer
  • W
e ha v e seen ho w the dynamic buer allo cation will tak e place in the constructor. W e ha v e seen ho w this buer ma y b e deleted and replaced with another as the result
  • f
an assignmen t. If w e no w ask
  • ur
fundamen tal question, for ev ery new is there a matc hing delete, w e see that there is
  • ne
remaining case w e ha v e not y et discussed. What happ ens if a v ariable
  • f
t yp e String is destro y ed? This will happ en, for example, when lo cal v ariables Define A destructor is a pr
  • c
e dur e that p erforms whatever houseke ep- ing is ne c- essary b efor e a variable is delete d are reco v ered at the end
  • f
a pro cedure. T
  • handle
this case, C ++ pro vides a mec hanism to p erform actions immediately b efore the p
  • in
t
  • f
destruction. This abilit y is pro vided b y means
  • f
a pro cedure called the destructor. The destructor for a class is a non-argumen t pro cedure with a name formed b y prep ending a tilde b efore the class name. The destructor sho wn in Figure 4.2 simply deletes the dynamically allo cated buer. With this facilit y , w e can no w matc h all allo cations and deletes, ensuring no memory leaks will
  • ccur.
Do not confuse the destructor with the delete
  • p
erator. The delete
  • p
erator is the function used to actually return memory to the heap manger. The destructor is c harged with whatev er \housecleaning" tasks are necessary b efore a v ariable disapp ears. Often this housecleaning in v
  • lv
es memory managemen t, but not alw a ys. In the next section w e will encoun ter a destructor that p erforms more than simply memory managemen t. The concept
  • f
a destructor in C ++ should also not b e confused with the notion
  • f
a nalize metho d in Ja v a. Destructors are tied to variables, while the nalize metho d is tied to a value. The destructor will b e in v
  • k
ed when a v ariable is ab
  • ut
to b e destro y ed, for example as so
  • n
as it go es
  • ut
  • f
scop e when a pro cedure returns,
  • r
when the v ariable itself is dynamically allo cated and has b een the target
  • f
a delete. A nalize metho d in
slide-15
SLIDE 15 64 CHAPTER 4. MEMOR Y MANA GEMENT Ja v a is in v
  • k
ed when the v alue holding the metho d is ab
  • ut
to b e reco v ered b y the garbage collector. There is no guaran tee in Ja v a when this will
  • ccur,
if ev er. Th us programmers cannot mak e assumptions concerning b eha vior in Ja v a based
  • n
the execution
  • f
co de in a nalize metho d. In this regard the C ++ programmer is
  • n
sligh tly safer ground, as the rules for when a destructor will b e in v
  • k
ed are carefully sp elled
  • ut
b y the language denition. An Execution T racer A clev er example that illustrates the use
  • f
constructors and destructors is an execution Note Con- structors and destructors c an b e use d for a variety
  • f
neste d ac- tivities tracer. The class T race tak es as argumen t a string v alue. The constructor prin ts a message using the string, and the destructor prin ts a dieren t message using the same string: class Trace f public: // constructor and destructor Trace (string); Trace (); private: string name; g; Trace::Trace (string t) : name(t) f cout << "Entering " << name << endl; g Trace::Trace () f cout << "Exiting " << name << endl; g T
  • trace
the
  • w
  • f
function in v
  • cations,
the programmer simply creates a declaration for a dumm y v ariable
  • f
t yp e T race in eac h pro cedure to b e traced: void procedureOne () f Trace dummy("Procedure One"); ... procedureTwo(); // pro c
  • ne
in v
  • k
es pro c t w
  • g
void procedureTwo ()
slide-16
SLIDE 16 4.3. HEAP RESIDENT MEMOR Y V ALUES 65 f Trace dummy("Procedure Two"); ... if (x < 5) f Trace dumTrue("x test is true"); ... g else f Trace dumFalse("x test is false"); ... g ... g Using the abilit y to declare v ariables lo cal to a blo c k, trace v ariables can ev en b e used to follo w the eect
  • f
conditional
  • r
lo
  • p
statemen ts. b y their
  • utput,
the v alues
  • f
t yp e T race will trace
  • ut
the
  • w
  • f
execution. A t ypical
  • utput
from this program migh t b e: Entering Procedure One Entering Procedure Two Entering x test is true ... Exiting x test is true Exiting Procedure Two Exiting Procedure One The auto ptr Class The relationship b et w een a string v alue and the underlying buer is a pattern that is rep eated man y times in programs. That is, there is an
  • b
ject that m ust dynamically allo cate another memory v alue in
  • rder
to p erform its in tended task. Ho w ev er, the lifetime
  • f
the dynamic v alue is tied to the lifetime
  • f
the
  • riginal
  • b
ject; it exists as long as the
  • riginal
  • b
jects exists, and should b e eliminated when the
  • riginal
  • b
ject ceases to exist. T
  • simplify
the managemen t
  • f
memory in this case, the standard library implemen ts a useful t yp e named auto ptr (see Section A.5 in App endix A). A simplied v ersion
  • f
auto ptr could b e describ ed as follo ws: 5 template <class T> class auto ptr f 5 This class description uses templates, whic h will b e describ ed in Chapter 9.
slide-17
SLIDE 17 66 CHAPTER 4. MEMOR Y MANA GEMENT public: auto ptr (T p) : ptr(p) f g auto ptr () : ptr(0) f g auto ptr() f delete ptr; g void
  • perator
= (T right) f delete ptr; ptr = right; g private: T
  • ptr;
g; The actual class is more robust and will handle assignmen ts and copies, but this form illustrates the k ey features. An auto ptr
  • b
ject simply holds a p
  • in
ter v alue, and will delete the memory referenced b y the p
  • in
ter when it itself is destro y ed. A revised string class that used auto p
  • in
ters w
  • uld
lo
  • k
similar to the follo wing: class string f ... private: auto ptr<char> buffer; g; void String::resize(in t size) f if ((buffer == 0) jj (size > strlen(buffer)) ) buffer = new char[1 + size]; g In this form it w
  • uld
not b e necessary to implemen t a destructor for the string class, since the default destructor w
  • uld
in v
  • k
e the destructor for the auto p
  • in
ter eld, whic h w
  • uld
in turn return the buer memory bac k to the heap manager. Auto p
  • in
ters should b e used an y time there is a
  • ne-to-one
corresp
  • ndence
b et w een
  • b
jects and an in ternal heap-allo cated memory , and the lifetime
  • f
the in ternal
  • b
ject is tied to the lifetime
  • f
the surrounding con tainer. 4.3.2 Reference Coun ts There are man y situations where t w
  • r
more
  • b
jects need to share a common data area. W e could imagine, for example, w an ting to c hange the seman tics for the assignmen t
  • f
slide-18
SLIDE 18 4.3. HEAP RESIDENT MEMOR Y V ALUES 67 strings so that t w
  • strings
w
  • uld
share a common in ternal buer. That is, subsequen t to the statemen t: a = c; b
  • th
v ariables a and c w
  • uld
reference the same buer: a c internal buer
  • *
H H H H j The dicult y with this in terpretation is that w e no longer ha v e a single unam biguous Define A r ef- er enc e c
  • unt
is the c
  • unt
  • f
the num- b er
  • f
p
  • int-
ers to a dy- namic al ly al- lo c ate d
  • bje
ct
  • b
ject that can b e said to \o wn" the dynamically allo cated v alue, and can therefore b e c harged with disp
  • sing
  • f
it when it is no longer needed. A solution to this problem is to augmen t the dynamic v alue with a coun t
  • f
the n um b er
  • f
p
  • in
ters that reference it. This coun t is termed a r efer enc e c
  • unt.
Care is needed to ensure the coun t is accurate; whenev er a new p
  • in
ter is added the coun t is incremen ted, and whenev er a p
  • in
ter is remo v ed the coun t is decremen ted. Figure 4.3 sho ws a revision
  • f
the String abstraction that incorp
  • rates
these c hanges. The metho d resize has here b een replaced with reassign. The metho d reassign replaces the curren t string reference with another. In doing so, it b
  • th
decremen ts the reference coun t
  • n
the
  • ld
string reference, and incremen ts the coun t
  • n
the new. P erforming the incremen t rst ensures the pro cedure will w
  • rk
in the sp ecial case where a v ariable is assigned to itself. If the reference coun t for the
  • ld
v alue b ecomes zero, the memory for the en tire string reference is returned to the heap manager, using the metho d delete. Before reco v ering the memory , the heap manger will execute the destructor for the string reference b eing deleted. This destructor will, in turn, return the buer to the heap manager. void String::reassign( St rin g: :St ri ng Ref er enc e
  • np)
f if (np) // incremen t coun t
  • n
new v alue np->count += 1; if (p) f // decremen t reference coun ts
  • n
  • ld
v alue p->count
  • =
1; if (p->count == 0) delete p; g p = np; // c hange binding g
slide-19
SLIDE 19 68 CHAPTER 4. MEMOR Y MANA GEMENT class String f public: // constructors String () : p(0) f g String (const char
  • right)
: p(0) f reassign(new StringReference(r igh t) ); g String (const String & right) : p(0) f reassign(right.p) ; g // destructor String () f reassign(0); g // assignmen t void
  • perator
= (const String & right) f reassign(right.p) ; g private: void reassign (StringReferenc e ); class StringReference f public: int count; char
  • buffer;
StringReference( con st char
  • right);
StringReference () f delete [ ] buffer; g g StringReference
  • p;
g void String::StringRe fe ren ce ::S tr ing Re fe ren ce (co ns t char
  • right)
f count = 0; buffer = new Char[1 + strlen(right)]; strcpy(buffer, right); g Figure 4.3: The Class String (V ersion Tw
  • )
slide-20
SLIDE 20 4.3. HEAP RESIDENT MEMOR Y V ALUES 69 The structure
  • f
the
  • b
ject holding b
  • th
the reference coun t and the buer is dened b y means
  • f
a nested class declared within the b
  • dy
  • f
the String class. The reader should note that although there are sup ercial syn tactic similarities, there are some seman tic dierences b et w een nested classes in C ++ and inner classes in Ja v a. These are discussed in more detail in Chapter 5. The v alues held b y reference coun ts can b e illustrated b y tracing the execution
  • f
a simple program. Imagine the follo wing: string g; // global string v alue void test () f string a = "abc"; string b = "xyz"; string c; c = a; a = b; g = b; g The follo wing table summarizes the reference coun ts asso ciated with the v alues "ab c" and "xyz" as the program executes: statement "abc" "xyz" string a = "abc"; 1 string b = "xyz"; 1 1 string c; 1 1 c = a; 2 1 a = b; 1 2 g = b; 2 2 end
  • f
exe cution: destructor for c 1 2 destructor for b 1 1 destructor for a 1 W e are left with a single reference (namely the global v ariable g) p
  • in
ting to the v alue "abc". The v alue "xyz" will ha v e b een reco v ered when the reference coun t reac hed zero, that is, when the v ariable a w as deleted.
slide-21
SLIDE 21 70 CHAPTER 4. MEMOR Y MANA GEMENT T est Y
  • ur
Understanding 1. What are some
  • f
the adv an tages
  • f
putting the programmer in con trol
  • f
memory managemen t? What are some
  • f
the disadv an tages? 2. What is a stac k residen t v alue? When is it allo cated? When is it deleted? 3. What are c haracteristics
  • f
stac k residen t v alues that are not necessarily c haracteristics
  • f
heap residen t v alues? 4. Explain the error in the follo wing program fragmen t: char
  • secretMessage()
f char messageBuffer[100 ]; strcpy (messageBuffer "Eat Ovaltean!"); return messageBuffer; g 5. Explain the slicing problem, and under what circumstances it will
  • ccur.
6. What is a heap residen t memory v alue? Ho w is this v alue allo cated? 7. What are the four t yp es
  • f
errors that can
  • ccur
in the reco v ery
  • f
heap residen t v alues? 8. What is a destructor? When is it in v
  • k
ed? 9. What is a reference coun t? 10. The follo wing statemen t is legal. It will create a temp
  • rary
string v alue for the righ t hand expression, then assign the temp
  • rary
to the left hand v ariable, b efore destro ying the temp
  • rary
. Assuming the reference coun ting sc heme is b eing used to implemen t the string data t yp e, trace the reference coun ts
  • n
the v arious in ternal buer v alues. string text = "initial text"; text = "new text";