Title: Memory Management
1C for Java Programmers
- Chapter 4
- Memory Management
2Memory Management
- Java background memory management
- Advantage allowing programmer to concentrate on
more application specific details - Disadvantage programmer has little control over
how memory management is performed. - C explicit memory management
- Advantagepermitting much more efficient use of
memory - Programmer must manage memory themselves
3Common Memory Errors in C
- Since programmers must manage memory themselves,
they often make mistakes. - Using a value before it has been initialized.
- Allocating memory for a value, then not deleting
it once it is no longer being used. - Using a value after it has been freed.
4Memory Model
- C model is much closer to the actual machine
representation than is Java memory model. - Permits an efficient implementation at the
expense of needing increased diligence on the
part of the programmer.
5Two major classes of memory
- Stack-resident - created automatically when a
procedure is entered or exited. - Heap-resident - must be explicitly created using
the new operator. - Categories same in Java and C, difference is
how heap values are recovered.
6Stack Resident Memory Values
- Values on a stack are strongly tied to procedure
entry and exit. - When a procedure begins execution, a new section
of the stack is created. - Java
- only primitive values are truly stack resident.
- objects and arrays are allocated on the heap.
7Program Example test()
- void test () // Java
-
- int i
- int a new int 10
- anObject ao new anObject()
- ..
- void test () // C
-
- int i,
- int a 10
- anObject ao
- ..
-
8Drawbacks Using Stack
- Lifetime of stack resident memory values is tied
to procedure entry exit. Stack resident values
cease to exist when a procedure returns. An
attempt to use resident value after deletion will
typically result in error. - Size of stack resident memory values must be
known at compile time, which is when the
structure of the activation record is laid out.
9Lifetime Errors
- Once a procedure returns from execution, any
stack resident values are deleted no longer
accessible. - A reference to such a value will no longer be
valid, although it may for a time appear to work.
10Program Example readALine()
- Char readALine ()
-
- char buffer1000 // declare a buffer for
the line gets(buffer) - gets(buffer) // read the line
return buffer - return buffer // return text of
line -
- Â
- String readALine (BufferedInput inp) throws
IOException -
- // create a buffer for the line
- String line inp.readLine()
- return line
-
- Â
- char lineBuffer // global declaration of
pointer to buffer - void readALine ()
-
- Â
- char buffertOOO // declare a
buffer for the line
11Size Errors - Slicing Problem
- Most severe restrictions of stack-based memory
management positions of values within the
activation record are determined at compile time.
- For primitive values pointers this is a small
concern. - For arrays the array bound must be known at
compile time. - For objects a limitation on the degree to which
values can be polymorphic.
12Array Allocations
- Stack resident arrays must have a size that is
known at compile time. - Often programmers avoid this problem by
allocating an array with a size that is purposely
too large. Â - Rule Never assume that just because an array is
big, it will always be big enough
13Programs with common errors
- char buffer200 // global avoids deletion
error - char readALine ()
-
- gets(buffer) // read the line
- return buffer
-
- What happens if user enters more than 200
characters?? - (Note many computer viruses make use of this
type of error in many applications) - Â
14Program Example - lets make a class
- class A
- public
- // constructor
- A () dataOne(2)
-
- // identification method
- virtual void whoAmI () printf("class A")
- private
- int dataOne
-
- class B public A
- public
- // constructor
- B () dataTwo(4)
- Â
- // identification method
- virtual void whoAmI () printf("class B")
- private
15Slicing Problem
- Java polymorphic - a variable declared as
maintaining a value of one class can be holding a
value derived from a child class. - In both Java and C, it is legal to assign a
value derived from class B to a variable declared
as holding an instance of class A. - A instanceOfA // declare instances of
- B instanceOfB // class A and B
- instanceOfA instanceOfBÂ
- instaceOfA.whoAmI() // surprizingly, it is
an A!
16Slicing Problem
- If you look carefully, the memory fields have
been sliced away
17Slicing (No)Problem for static variables
- Rule Static variables are never polymorphic.
- Makes it difficult to use OOP features with
static variables - Which is why OOP programs end up using pointers a
lot
18Slicing does not occur with pointers
- Note carefully that slicing does not occur with
references or with pointers - A referenceToA instanceOfB
- referenceToA.whoAmI() // will print
class B - Â B pointerToB new B()
- A pointerToA pointerToB()
- pointerToA -gt whoAmI() // will print
class BÂ - Slicing only occurs with objects that are stack
resident OOP programs make the majority of
their objects heap resident.
19The Point to Remember
- The important point to remember
- The rules for method binding are different for
static variables than they are for pointers and
references - Static variables are never polymorphic
20Heap Resident Memory Values
- Heap resident values are created using the new
operator. - Memory for such values resides on the heap, or
free store, which is a separate part of memory
from the stack. - Typically accessed through a pointer, which will
often reside on the stack. - Java hides the use of this pointer value, dont
need be concerned with it. - In C, pointer declaration is explicitly stated.
21Heap Resident Memory Values
- void test () // Java
-
- A anA new A ( )
- .
-
- Â
- void test () // C
-
- A anA new A // note pointer
declaration - if (anA 0) ... // handle no
memory situation - delete anA
-
22Recovery of Heap Based Memory
- Java incorporates garbage collection into its
run-time library the garbage collection system
monitors the use of dynamically allocated
variables, and will automatically recover and
reuse memory that is no longer being accessed. - In C, leaves this task to the programmer
dynamically allocated memory must be handed back
to the heap manager using the delete operator.
The deletion is performed by simply naming the
pointer variable.
23Common Memory Errors in C
- Forgetting to allocate a heap-resident value, and
using a pointer as if it were referencing a
legitimate value. - char buffer
-
- buffer a
24Common Memory Errors in C
- Forgetting to hand unused memory back to the heap
manager. - void foo ()
- char buffer new char100
-
-
- // does not automatically recover heap memory
25Common Memory Errors in C
- Attempting to use memory values after they have
been handed back to the heap manager. - char buffer new char100
-
- delete buffer // return memory to heap manager
-
- cout ltlt buffer
- // oops, who knows what will happen
26Common Memory Errors in C
- Invoking the delete statement on the same value
more than once, thereby passing the same memory
value back to the heap manager. - char buffer new char100
-
- delete buffer
-
- delete buffer //opps, odd things happen
27Match memory allocations and deletions
- Memory leak an allocation of memory that is
never recovered - cause the memory requirements
for the program to increase over time. Eventually
the heap manager will be unable to service a
request for further memory, and the program will
halt. - Rule Always match memory allocations and
deletions
28Simple Techniques to manage heap
- Hide the allocation and release of dynamic memory
values inside an object. - Maintaining a reference count that indicates the
number of pointers to the value. When this count
is decremented to zero, the value can be
recovered.
29Encapsulating Memory Management
- String literals in C are very low level
abstractions. - A string literal in C is treated as an array of
character values, and the only permitted
operations are those common to all arrays. - The String data type in Java is designed to
provide a higher level of abstraction. - A version of this data structure is provided in
the new Standard Template Library.
30Program Example resize()
- void Stringresize(int size)
- if (buffer O) // no previous allocation
- buffer new char1 size
- else if (size gt strlen(buffer))
- Â class String
- Public
- String () buffer(0) // constructors
- String (const char right) buffer(0)
- resize(strlen(right)) strcpy(buffer, right)
- String (const String right) buffer(0)
- resize(strlen(right.buffer)) strcpy(buffer,
right.buffer)
- String () delete buffer // destructorÂ
- void operator (const String right) //
assignment - resize(strlen(right.buffer))
strcpy(buffer, right.buffer) - private
- void resize (int size)
- char buffer
-
- delete buffer // recover old value
- buffer new char1 size
31Destructor in C
- Destructor a procedure that performs whatever
housekeeping is necessary before a variable is
deleted. - a non-argument procedure with a name formed by
prepending a tilde before the class name. - delete operator is the function used to actually
return memory to the heap manger
32Example Execution Tracer
- The class Trace takes as argument a string value.
The constructor prints a message using the
strings and the destructor prints a different
message using the same string - To trace the flow of function invocations, the
programmer simply creates a declaration for a
dummy variable of type Trace in each procedure to
be traced
33Program Example class Trace
- class Trace
- public
- Trace (string) // constructor and destructor
- trace ()
- private
- string name
-
- Trace Trace (string t) name(t)
- cout ltlt "Entering " ltlt name ltlt endl
- Trace Trace () count ltlt Exiting ltlt name
ltlt endl
34Program Example procedures
- void procedureOne ()
- Trace dummy("Procedure One")
- .
- procedureTwo() // proc one invokes
proc two -
- Â
- void procedureTwo ()
- Trace dummy("Procedure Two")
- .
- If (x lt 5)
- Trace dumTrue("x test is true")
- ..
-
- else
- Trace dumFalse("x test is false")
- ..
- ..
-
35Test your understanding
- What are some advantages of having programmer
control memory management? - What are some disadvantages?
36Test your understanding
- What is a stack resident value? What is a heap
resident value? - What are restrictions placed on stack resident
values? - When are stack resident values recovered? When
are heap values recovered?
37Test your understanding
- Explain the error in the following
- Char secretMessage ()
- char messageBuffer100
- strcpy (messageBuffer, Eat Ovaltean!)
- return messageBuffer
38Test your understanding
- What is the slicing problem? Under what
circumstances does it occur?
39Test your understanding
- What are four types of errors that can occur
during the process of recovery of heap resident
values?