pointers and memory allocation -l. grewe

61
Pointers and Memory Allocation -L. Grewe

Upload: hera

Post on 19-Jan-2016

49 views

Category:

Documents


3 download

DESCRIPTION

Pointers and Memory Allocation -L. Grewe. Objectives. Why and What are Pointers Create Pointers in C++ Memory Allocation Defined Memory Allocation/Deallocation in C++ Potential Problems with Pointers and Memory. What's the point of pointers?...why?. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Pointers and Memory Allocation -L. Grewe

Pointers and Memory Allocation-L. Grewe

Page 2: Pointers and Memory Allocation -L. Grewe

Objectives

•Why and What are Pointers

•Create Pointers in C++

•Memory Allocation Defined

•Memory Allocation/Deallocation in C++

•Potential Problems with Pointers and Memory

Page 3: Pointers and Memory Allocation -L. Grewe

What's the point of pointers?...why?• Pointers can be used as variable length

arrays.

• Pointers can be used for advanced data structures.

• Pointers can be "cheaper" to pass around a program.

• Can sometimes be difficult to program without them-

Page 4: Pointers and Memory Allocation -L. Grewe

Motivating Example – for pointers and memory allocation

Bag class

– bag::CAPACITY constant determines the capacity of every bag

– wasteful (if too big) and hard to reuse (if too small)

• need to change source code and recompile

Solution:

– provide control over size in running time

– dynamic arrays

– pointers and dynamic memory

Page 5: Pointers and Memory Allocation -L. Grewe

Pointers

Pointer is a variable that contains the address of a variable

– Low level representation of the hardware implementation

Typical machine has an array of memory cells (usually bytes (8-bits)) numbered (addressed) consecutively

A pointer is a group of cells that can hold an address

– On modern computers memory address requires 32 – 64 bits (4 – 8 bytes)

|| || || || ... ......CpC

pC = pointer to variable C

Page 6: Pointers and Memory Allocation -L. Grewe

Pointer Variable

Let’s look at local variables

Q: What’s the value of i?

??900900

904904

908908

912912

916916

……

int i; ii

By this declaration, a cell By this declaration, a cell of 4 adjacent bytes (in of 4 adjacent bytes (in some machines) are some machines) are allocated in the local allocated in the local memory (called memory (called stack stack

memorymemory))Address 9## is just Address 9## is just

for illustration.for illustration.Real address may Real address may

have 64 bitshave 64 bits

Page 7: Pointers and Memory Allocation -L. Grewe

Pointer Variable

Let’s assign a value to i

Q: How can we get the address?

4242900900

904904

908908

912912

916916

……

int i;

i = 42;

ii

The assignment put The assignment put number 42 in the cell. The number 42 in the cell. The memory address of the 1memory address of the 1stst byte is the byte is the address of the address of the

variablevariable i i

– – the the pointerpointer to i to i

Page 8: Pointers and Memory Allocation -L. Grewe

Pointer Variable

First let’s have a look at local variables

Q: Where can we store &i?

4242900900

904904

908908

912912

916916

……

int i;

i = 42;

cout << &i;

ii

& (ampersand) operator& (ampersand) operator- “ “address of address of ” ” operatoroperator

- &i is 900 !&i is 900 !

-Note: two meanings of &Note: two meanings of &

Page 9: Pointers and Memory Allocation -L. Grewe

A Pointer Variable

A pointer variable can store a memory address in this case to an int

Q: How can we point i_ptr to i?

4242

??

900900

904904

908908

912912

916916

……

int i=42;

int *i_ptr;

ii

i_ptri_ptr

1.1. the type of the data the type of the data that the pointer points that the pointer points

to: intto: int2.2. an asterisk (*)an asterisk (*)

3.3. the name of the newly the name of the newly declared pointer: i_ptrdeclared pointer: i_ptr

Page 10: Pointers and Memory Allocation -L. Grewe

Pointer Variable

Assign the address of i to i_ptr

4242

??

900900

904904

908908

912912

916916

……

int i=42;

int *i_ptr;

i_ptr = &i;

ii

i_ptri_ptr

What are the results ofWhat are the results of- cout << i; cout << i;

- cout << i_ptr;cout << i_ptr;- cout << &i_ptr;cout << &i_ptr;

Page 11: Pointers and Memory Allocation -L. Grewe

Pointer Variable

The i_ptr holds the address of an integer, not the integer itself

4242

900900

900900

904904

908908

912912

916916

……

int i=42;

int *i_ptr;

i_ptr = &i;

ii

i_ptri_ptr

Two ways to refer to iTwo ways to refer to i- cout << i; cout << i;

- cout << *i_ptr;cout << *i_ptr; - - dereferencing operatordereferencing operator * *

Page 12: Pointers and Memory Allocation -L. Grewe

Use of & and * in C/C++

When is & used?

When is * used?

& "address (reference) operator" which gives or produces the memory address of a data variable

* “dereferencing operator" which provides the contents in the memory location specified by a pointer

&expr Evaluates to the address of the location expr evaluates to

*expr Evaluates to the value stored inthe address expr evaluates to

Page 13: Pointers and Memory Allocation -L. Grewe

Address (reference) Operator

Operator of address or dereference (&)

– It is used as a variable prefix and can be translated as "address of“

– &variable1 can be read as "address of variable1"

Example:

c = 13;

b = &c; // b = 1ef

a = *b; // a = 13

1efb:

13c(1ef): 13

a:

Page 14: Pointers and Memory Allocation -L. Grewe

Dereference Operator

Using a pointer we can directly access the value stored in the variable pointed by it

– precede the pointer identifier with the dereference operator (*)

– that can be literally translated to "value pointed by".

Example:

a = *b;

– a is equal to value pointed by b. 1efb:

131ef: 13

a:

Page 15: Pointers and Memory Allocation -L. Grewe

Concept of Address and PointersMemory can be

conceptualized as a linear set of data locations.

Variables reference the contents of a locations

Pointers have a value of the address of a given location

Contents1

Contents11

Contents16

ADDR1ADDR2ADDR3ADDR4ADDR5ADDR6

***

ADDR11

**

ADDR16

Page 16: Pointers and Memory Allocation -L. Grewe

Terminology – How to make a pointer in C/C++

Declaring a variable

int num = 5;

Declaring a pointer

int *nptr = 0;

Assigning an address to a pointer

nptr = &num;

Dereferencing a pointer

printf("%d",*nptr);

Page 17: Pointers and Memory Allocation -L. Grewe

Declaring Multiple Pointers

How to declare two pointers in a line

char *c1_ptr, *c2_ptr;

– instead of

char* c1_ptr, c2_ptr;

TIP: naming convention: for clarity, use _ptr or cursor for pointer variables

Page 18: Pointers and Memory Allocation -L. Grewe

Assignment Operators with Pointers

p2 = p1

int i = 42;

int *p1, *p2;

p1 = &i;

p2 = p1;

4242 ii900900

address value name address value name

??904904 ??908908

Both p1 and p2 point to the same integerBoth p1 and p2 point to the same integer

900900 p1p1904904 900900 p2p2

4242

??

??

900900

904904

908908

912912

916916

……

ii

p1p1

p2p2

900900

900900

Page 19: Pointers and Memory Allocation -L. Grewe

Assignment Operators with Pointers

*p2 = *p1

int i = 42;

int *p1, *p2;

p1 = &i;

*p2 = *p1;

4242 ii900900

address value name address value name

??904904 ?? p2p2908908

p2 doesn’t point to anywhere, so p2 doesn’t point to anywhere, so assigning value to *p2 will cause a assigning value to *p2 will cause a

running time error!running time error!

900900 p1p1904904

4242

??

??

900900

904904

908908

912912

916916

……

ii

p1p1

p2p2

900900

XX

Page 20: Pointers and Memory Allocation -L. Grewe

POINTERSExamples of pointer declarations:

FILE *fptr;

int *a;

float *b;

char *c;

The asterisk, when used as above in the declaration, tells the compiler that the variable is to be a pointer, and the type of data that the pointer points to, but NOT the name of the variable pointed to.

Page 21: Pointers and Memory Allocation -L. Grewe

An Example

Lets look at some code

Page 22: Pointers and Memory Allocation -L. Grewe

POINTERS

Consider the statements:

#include <stdio.h>

int main ( )

{

FILE *fptr1 , *fptr2 ; /* Declare two file pointers */

int *aptr ; /* Declare a pointer to an int */

float *bptr ; /* Declare a pointer to a float */

int a ; /* Declare an int variable */

float b ; /* Declare a float variable */

Page 23: Pointers and Memory Allocation -L. Grewe

POINTERS

/* Then consider the statements: */

aptr = &a ;

bptr = &b ;

fptr2 = fopen ( "my_out_file.dat" , "w" ) ;

fptr1 = fopen ( "my_in_file.dat" , "r" ) ;

if ( fptr1 != NULL )

{

fscanf ( fptr1, "%d%f" , aptr , bptr ) ;

Page 24: Pointers and Memory Allocation -L. Grewe

POINTERS

fprintf ( fptr2, "%d %d\n" , aptr , bptr ) ;

fprintf ( fptr2, "%d %f\n" , *aptr , *bptr ) ;

fprintf ( fptr2, "%d %f\n" , a , b ) ;

fprintf ( fptr2, "%d %d\n" , &a , &b ) ;

return 0 ;

}

Assuming that the above is part of a program that runs without error and the input file does open, what would be printed to the file

By the first fprintf? By the second fprintf?

By the third fprintf? By the fourth fprintf?

3 92.66

my_in_file.dat

Page 25: Pointers and Memory Allocation -L. Grewe

POINTERS

fprintf ( fptr2, "%d %d\n" , aptr , bptr ) ;

fprintf ( fptr2, "%d %f\n" , *aptr , *bptr ) ;

fprintf ( fptr2, "%d %f\n" , a , b ) ;

fprintf ( fptr2, "%d %d\n" , &a , &b ) ;

return 0 ;

}

Assuming that the above is part of a program that runs without error and the input file does open, what would be printed to the file

By the first fprintf? By the second fprintf?

By the third fprintf? By the fourth fprintf?

3 92.66

my_in_file.dat

Address_a Address_b392.663 92.66Address_a Address_b

my_out_file.dat

Page 26: Pointers and Memory Allocation -L. Grewe

Arrays and Pointers

Page 27: Pointers and Memory Allocation -L. Grewe

Arrays and Pointers

The name of an array is the pointer to the address containing the first element in the array.

Let’s look at how arrays and pointers interact

27

Page 28: Pointers and Memory Allocation -L. Grewe

Arrays and Pointers

int scores[50];

int * p = scores;

*p = 99;

cout << scores[0]; // "99"

p++; // ok

scores++; // error: scores is const

An array name is assignment-compatible with a pointer to the array's first element. In the following example, *p refers to scores[0].

Page 29: Pointers and Memory Allocation -L. Grewe

Traversing an Array

int scores[50];

int * p = scores;

for( int i = 0; i < 50; i++)

{

cout << *p << endl;

p++; // increment the pointer

}

C and C++ programmers often use pointers to traverse arrays. At one time, such code ran more efficiently, but recent optimizing compilers make array subscripts just as efficient.

Page 30: Pointers and Memory Allocation -L. Grewe

Array Example

char s[6];s[0] = ‘h’;s[1] = ‘e’;s[2]= ‘l’;s[3] = ‘l’;s[4] = ‘o’;s[5] = ‘\0’;

printf (“s: %s\n”, s);

s: hello

expr1[expr2] in C is just syntactic sugar for*(expr1 + expr2)

Page 31: Pointers and Memory Allocation -L. Grewe

Array Example 2 – access via pointers

char s[6];*s = ‘h’;

*(s + 1) = ‘e’;2[s] = ‘l’;3[s] = ‘l’;

*(s + 4) = ‘o’;5[s] = ‘\0’;

printf (“s: %s\n”, s);s: hello

expr1[expr2] in C is just syntactic sugar for*(expr1 + expr2)

Page 32: Pointers and Memory Allocation -L. Grewe

Multidimensional Arrays

Declaring

int myIntArray2D[20][30];

Orint** myIntArray2D;

myIntArray2D = new int*[10];

for (int i=0; i<10; i++)

myIntArray2D[i] = new int[10];

Accessing an element

int x = myIntArray2D[2][6]; // row 3, col 7

Page 33: Pointers and Memory Allocation -L. Grewe

Destroying 2D array

for (int i=0; i<10; i++)

delete [] myIntArray2D[i];

delete [] myIntArray2D;

NOTE: More dimensions -> more loops!

Page 34: Pointers and Memory Allocation -L. Grewe

MultiDemensional Array concept via 1D Array

A solution: use single dimension array instead:

int* myIntArray2D = new int[100];

int x = myIntArray2D[2*10 + 6]; // row 3, col 7

• Possible advantage:

Can be faster access because of simplified memory structure

Page 35: Pointers and Memory Allocation -L. Grewe

Functions and Pointers

Page 36: Pointers and Memory Allocation -L. Grewe

Pointers and Functions

Pointers can be used to pass addresses of variables to functions, thus allowing the called function to alter the values stored there.

Page 37: Pointers and Memory Allocation -L. Grewe

Pointers and Functions

If instead of passing the values of the variables to the called function, we pass their addresses, so that the called function can change the values stored in the calling routine. This is known as "call by reference" since we are referencing the variables.

The following shows the swap function modified from a "call by value" to a "call by reference". Note that the values are now actually swapped when the control is returned to main function.

Page 38: Pointers and Memory Allocation -L. Grewe

Pointers with Functions (example)

#include <stdio.h>

void swap ( int *a, int *b ) ;

int main ( )

{

int a = 5, b = 6;

printf("a=%d b=%d\n",a,b) ;

swap (&a, &b) ;

printf("a=%d b=%d\n",a,b) ;

return 0 ;

}

void swap( int *a, int *b )

{

int temp;

temp= *a; *a= *b; *b = temp ;

printf ("a=%d b=%d\n", *a, *b);

}

Results:

a=5 b=6

a=6 b=5

a=6 b=5

Page 39: Pointers and Memory Allocation -L. Grewe

Function Returning an Address

Student * MakeStudent()

{

Student * pS = new Student;

return pS;

}

A function can return the address of an object that was created on the heap. In this example, the function's return type is pointer to Student.

(more)

Page 40: Pointers and Memory Allocation -L. Grewe

Receiving a Pointer

Student * pS;

pS = MakeStudent();

// now pS points to a Student

(continued)...

The caller of the function can receive the address and store it in a pointer variable. As long as the pointer remains active, the Student object is accessible.

Page 41: Pointers and Memory Allocation -L. Grewe

Pointers and Classes

41

Page 42: Pointers and Memory Allocation -L. Grewe

Pointers in Classes

class Student {

public:

Student();

~Student();

private:

string * courses; // array of course names

int count; // number of courses

};

// more...

Pointers are effective when encapsulated in classes, because you can control the pointers' lifetimes.

Page 43: Pointers and Memory Allocation -L. Grewe

Pointers in Classes

Student::Student()

{

courses = new string[50];

count = 0;

}

Student::~Student()

{

delete [] courses;

}

The constructor creates the array, and the destructor deletes it. Very little can go wrong,...

Page 44: Pointers and Memory Allocation -L. Grewe

STL – Collections

• i.e. vector - Automatic memory management when adding and deleting elements

#include <vector>

void main() {

std::vector<int> intList;

intList.push_back(10);

intList.push_back(12);

std::cout << intList[1] << std::endl;

intList.clear();

}

Page 45: Pointers and Memory Allocation -L. Grewe

More Pointer Manipulation

Page 46: Pointers and Memory Allocation -L. Grewe

Assigning Pointers to Pointers

Must be of the same type

If not, must use a cast operator

Exception is type void

– Generic pointer

– Can be assigned to any pointer type

– Any pointer type can be assigned to it

– Cannot be dereferenced (must cast it first)

Page 47: Pointers and Memory Allocation -L. Grewe

Assigning Pointers to Pointersint num = 1234567890; /*0x499602D2*/

char ch = 'A';

int *iptr = &num;

char *cptr = &ch;

iptr = (int *)cptr;

/*cast char pointer to integer pointer*/

printf("*iptr=%c\n",*iptr);

/* *iptr=A (no data lost)*/

iptr = &num;

cptr = (char *)iptr;

/*cast integer pointer to char pointer*/

printf("*cptr=%d\n",*cptr);

/* *cptr=-46 (loss of data)*/

/*0x499602D2 => D2 => 1101 0010 => -46*/

Page 48: Pointers and Memory Allocation -L. Grewe

We can also have pointers to pointers:

Pointers to pointers (different than previous slide

which was about assigning a pointer to another pointer)

int number= 5;int *ptrtonumber;int **ptrtoptrtonumber;ptrtonumber= &number;*ptrtoptrtonumber= &ptrtonumber;*(*ptrtoptrtonumber)= 6;

5

ptrtonumber

ptrtoptrtonumber

number

Page 49: Pointers and Memory Allocation -L. Grewe

Generic Pointer - void *int num = 1234567890;

char ch = 'A';

int *iptr = &num;

char *cptr = &ch;

void *vptr = NULL;

vptr = iptr;

printf(“*vptr=%d\n",*((int *)vptr));

/* *vptr=1234567890 */

/* cast void to int pointer*/

vptr = cptr;

printf(“*vptr=%c\n",*((char *)vptr));

/* *vptr=A */

/* cast void to a char pointer*/

Page 50: Pointers and Memory Allocation -L. Grewe

Arithmetic and Logical Operations on Pointers

A pointer may be incremented or decremented

An integer may be added to or subtracted from a pointer.

Pointer variables may be subtracted from one another.

Pointer variables can be used in comparisons, but usually only in a comparison to NULL.

Page 51: Pointers and Memory Allocation -L. Grewe

Arithmetic Operations on Pointers

When an integer is added to or subtracted from a pointer, the new pointer value is changed by the integer times the number of bytes in the data variable the pointer is pointing to.

For example, if the pointer valptr contains the address of a double precision variable and that address is 234567870, then the statement:

valptr = valptr + 2;

would change valptr to 234567886

Page 52: Pointers and Memory Allocation -L. Grewe

Problems with Pointers(part 1)

52

Page 53: Pointers and Memory Allocation -L. Grewe

Memory leaksIf we allocate memory but don't free it this

is a "memory leak"void my_function (void){ int *a; a= malloc(100*sizeof(int)); /* Do something with a*/ /* Oops – forgot to free a */}

Every time we call this function it "steals" 100 ints worthof memory. As we call this function more the computersmemory will fill up.

Page 54: Pointers and Memory Allocation -L. Grewe

Rogue pointers

Rogue pointers are pointers to unassigned memory. If we try to

access rogue pointers we will be writing to unassigned memory

int *calc_array (void){ int *a; int b[100]; /* Calculate stuff to go in b */ a= b; /* Make a point to the start of b*/ return a; /* Ooops – this isn't good */}

Page 55: Pointers and Memory Allocation -L. Grewe

Dangling Pointers

double * pD = new double;

*pD = 3.523;

.

.

delete pD; // pD is dangling...

.

.

*pD = 4.2; // error!

A dangling pointer is created when you delete its storage and then try to use the pointer. It no longer points to valid storage and may corrupt the program's data.

Page 56: Pointers and Memory Allocation -L. Grewe

Avoid Dangling Pointers

delete pD;

pD = NULL;

.

.

if( pD != NULL ) // check it first...

*pD = 4.2;

To avoid using a dangling pointer, assign NULL to a pointer immediately after it is deleted.

And, of course, check for NULL before using the pointer.

Page 57: Pointers and Memory Allocation -L. Grewe

Another possible problem with Pointers

class Student {

public:

Student();

~Student();

private:

string * courses; // array of course names

int count; // number of courses

};

// more...

When you try to copy a Class that has a pointer for a variable. RECALL ----

Page 58: Pointers and Memory Allocation -L. Grewe

Lets make an instance of our class &copy it

Student X;

Student Y(X); // construct a copy

X.AddCourse("cop 3337");

cout << Y.GetCourse(0); // "cop 3337"

...except when making a copy of a Student object. The default copy constructor used by C++ leads to problems. In the following example, a course assigned to student X AFTER THE COPY ends up in the list of courses for student Y.

Page 59: Pointers and Memory Allocation -L. Grewe

Pointers in Classes

Student::Student(const Student & S2)

{

count = S2.count;

courses = new string[count];

for(int i = 0; i < count; i++)

courses[i] = S2.courses[i];

}

To prevent this sort of problem, we create a copy constructor that performs a so-called deep copy of the array from one student to another.

Page 60: Pointers and Memory Allocation -L. Grewe

Pointers in Classes

Student & Student::operator =(const Student & S2)

{

delete [] courses; // delete existing array

count = S2.count;

for(int i = 0; i < count; i++)

courses[i] = S2.courses[i];

return *this;

}

For the same reason, we have to overload the assignment operator.

Page 61: Pointers and Memory Allocation -L. Grewe

C++ Containers in Classes

class Student {

public:

Student();

private:

vector<string> courses;

};

When you use Standard C++ containers such as lists and vectors in classes, there is no problem with the default copy constructor in C++. All containers are experts at allocating and copying themselves.