CSE 143 Dynamic Memory: Intro

•Problem: All of our data structures so far have a “maximum” size. Dynamic Memory •This size is fixed at compile time. •Often this is acceptable, but many real [Chapter 7] applications need to grow and shrink the amount of memory consumed by an ADT at run time. •Most languages provide some form of dynamic memory. •++ provides an interface to dynamic memory via two new operators: new and delete.

10/19/98 1 10/19/98 2

Data and Memory Ways of Using Memory

•Objects of different types may requires differing •Static - allocated at program startup time, exists amounts of memory throughout the execution of the entire program •Built-in types: implementation dependent •Automatic - implicitly allocated upon function •PC (typical): entry, deallocated on exit char: 1 byte (8 bits) void foo (char x) { int: 4 bytes (2 bytes on older systems) int temp; double: 8 bytes . . . • // x and temp are deallocated here Programmer defined types: depends on size of } data members •Dynamic - explicitly allocated and deallocated by •could be few bytes or thousands of bytes the programmer

10/19/98 3 10/19/98 4

Pointers: Review Pointer Variables

•Every memory cell in a computer’s memory has •By "address of an object" we mean the address of two characteristics: the first memory cell used by the object •A value (contents) •A pointer variable is one that contains the address •A unique address of another data object as its value. •Every object in the program occupies a range of •To declare a pointer variable: memory cells Type* name; •Suppose we have: int x; • •To access the value of x: Example: x int* intPtr; •To access the address of x: char* charPtr; &x BigNat* bigNatPtr; 10/19/98 5 10/19/98 6

CSE 143 1 Pointers and Types Two Important Operators

•Pointers to different types themselves are •The address-of operator &: different types int x = 45; int* p = &x; double *dpt; • BankAccount * bp; The dereference operator *: *p = 30; •C/C++ considers dpt and bp to have different p = 72; // what’s the problem here? types •even though under the hood they are both just memory addresses •Types have to match in many contexts •e.g. actual param types matching formal param types •pointers are no exceptions

10/19/98 7 10/19/98 8

The Pointer Types & Ops

•During program execution, a pointer variable can •Domain (possible values) be in one of the following states: •The set of all memory addresses along with the NULL •Unassigned pointer •Pointing to a data object •Operations valid on pointers of all types (pp292- •Contain the special value NULL 293). We’ll cover only a subset: •The constant NULL is defined as 0 in stddef.h, = (assignment) and is used to mean a pointer that does not point int* p = &someInt; to any object. * (dereference) • *p = 345; NULL is compatible with all pointer types == (equality test) if (ptr1 == ptr2) { . . . }

10/19/98 9 10/19/98 10

More Pointer Operations Reference Types

!= (test for inequality) •We can declare variables or params of reference if (ptr1 != ptr2) { . . . } types: Type& rname //rname will hold an alias to something delete (deallocate) //of type Type delete ptr; // more on this later •Example: int x; -> (select a member of a pointed-to object) int& refx = x; // a ref. variable must be initialized

void foo (BankAccount* b) { x = 40; b->printBalance(); cout << refx; // what’s the output? } refx = 20; cout << x; // what’s the output? •Main use: for parameters

10/19/98 11 10/19/98 12

CSE 143 2 Writing Swap (Old School) Writing Swap (New School)

•In 142, you used pointers to write functions which •C++ lets us use reference parameters, leading to side-effected their actual parameters: much cleaner code:

void swap(int& a, int& b) { void swap(int* p, int* q) { int temp = a; int temp; a = b; temp = *p; b = temp; *p = *q; } *q = temp; } // example call: swap(intOne, intTwo); // note: no & // example call: swap(&intOne, &intTwo); // don’t forget the &

10/19/98 13 10/19/98 14

Allocation & Deallocation The Heap

•Allocate dynamic memory with the new operator: •Objects created by new come from a region of •The expression new Type returns a pointer to a newly memory set aside for dynamic objects (called the created object of type Type: heap, or free store). int* p; • char* str; The new operator obtains a chunk of memory p = new int; // allocate a single int from the heap; delete returns that memory to the str = new char[10]; // allocate an array of chars heap. •Deallocate memory with the delete operator: •In C++ the programmer must manage the heap. • delete Pointer deallocates the object pointed to by •Dynamic data is unnamed and can only be Pointer delete p; // deallocating a simple object accessed through pointers. delete [] str; // deallocating an array of objects

10/19/98 15 10/19/98 16

Arrays vs. Pointers Arrays ≠ Pointers!

•An array name refers to the address of the first int * ip; //what memory is allocated? element of the array int iarr[10]; //what memory is allocated? •Array notation can be used with pointers bool checkstring (char aName[], char * bName) { int i = 0; iarr[0] = 100; //good or bad? while (bName[i] != ‘\0’){ ip[0] = 200; //good or bad? aName[i] = bName[i]; i++; ip = iarr; //good or bad? } iarr = ip; //good or bad? aName[i] = ‘\0’; if (islower (*aName)){ ip = new int[20]; //good or bad? ... } iarr = new int[20];//good or bad?

10/19/98 17 10/19/98 18

CSE 143 3 Two Pesky Problems Garbage ()

•Inaccessible objects and memory leaks •Example local vars. heap •An inaccessible object is a dynamic object without any int* p; p pointers pointing to it p = new int; *p = 45; • Sometimes called garbage. p = new int; //! •Accumulating garbage leads to a memory leak. *p = 55; • Dangling pointers • •A pointer that points to where an object used to be (even Example 2 int *p, *q; though the object's memory has been deallocated) is a p = new int; p . q = new int; •Both are serious problems *p = 45; *q = 55; q •dangling pointer is especially dangerous p = q; //!

10/19/98 19 10/19/98 20

Dangling Pointers Dynamic Data Guidelines

•Example 1 local vars. heap •Avoid creating garbage when invoking new or int *p = new int; moving pointers. int *q; p *p = 45; •The new operator returns a pointer to an object. q = p; If the object’s type is a class, then the constructor delete p; q *q = 55; // oops! has been called. If not, the object is still •Example 2 uninitialized. char* broken() { •Don’t dereference an unassigned pointer. char buffer[80]; •After delete, the pointer value is unassigned cin >> buffer; Destroyed when function exits!! return buffer; (don't assume NULL) } charPtr = broken(); // charPtr is dangling

10/19/98 21 10/19/98 22

CSE 143 4