©zachary wartell, uncc9/28/2006 11:30 am 1 thinking in c++ revision: 10/16/2007 8:26:20 pm...
TRANSCRIPT
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 1
Thinking in C++
Revision: 10/16/2007 8:26:20 PMCopyright Professor Zachary Wartell, University of North Carolina
All Rights Reserved
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 2
C++ Systems Programming Language
●Systems Programming: operating systems, database systems, device drivers, compilers, byte-code interpreters, high-level graphics libraries (‘game engines’)
-performance matters: -generate native machine language instructions-may hand optimize with assembly lang.
-memory management approaches:-each type of above system is best served by diff. memory
management approach-single system may need multiple approaches
●Applications Programming: spreadsheet, word processor, WWW stuff, game scripts
-performance: easy of programming versus run-time efficiency-memory management: may accept standard garbage collection
●C = ‘platform independent assembly language’, C++ = C +OOP
-for systems programming, for applications programming (?)
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 3
C++ & System Programming Conceptual Stumbling Blocks
• file organization – separate code implementation and class/type definitions
• variables – do variables name an object or a reference to an object?
• pointers – addresses, address arithmetic, arrays, address for function parameter, function pointer
• explicit dynamic memory allocation and deallocation• constructors/destructors• C++ reference• C++ polymorphism• memory errors – C++ says “Yes, Sir!”
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 4
library code
header files
C++ Files
• source code files (.cpp, etc.) – function and member function implementation and global variable definitions
• header files (.h or no extension) – data types, function prototypes, global variable declarations used by multiple source code files
COMPILER
LINKER
object code
executable code
#include
source code header files
#include
library code
header files
std C++ library
other library(s)
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 5
library code
header files
Example
COMPILER
LINKER
object code
executable code
#include
source code header files
#include
library code
header files
std C++ library
other library(s)
List.cppmain.cpp
List.h
main.obj,List.obj
List.exe
iostream
cppstdlib.li
b
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 6
Example
main.cpp#include "List.h"#include <iostream>…int main (int argc, char** argv) { … }
List.cpp#include "List.h"
// constructorList::List() {…}
// destructorList::~List() {…}
// print listList::print () {…}
List.h
class List {
… List(); ~List(); void print();
… ListNode* head; ListNode* tail; };
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 7
Java vs C++ Variables
• variables of built-in type versus class type• process address space• level of indirection
– allocation and operator= – operator==– pass-by value
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 8
C++ and Java Variables• C++
– class variables and built-in type variables are placeholders for the memory address of the class or built-in objects
• Java:– built-in variable is placeholder for memory address of built-in
object– but class variable is placeholder for memory address of
reference to class object
Javaclass Vehicle {…}
…int a,b;Vehicle c,d;a = 10;c = new Vehicle;d = c;d.wheelCount = 4;
C++class Vehicle {…}
…int a,b;Vehicle c,d;a = 10;c.wheelCount = 4;d.wheelCount = 6;
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 9
Review: Process Address Space
Code
StaticData
Stack
0x00000000
0xfffffffeHeap
0xffffffff
….
user spaceos space
unallocated
Stack Frame
Arguments
IPFP
Local Variables
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 10
Level of Indirection – instance allocation and =
0x000100100x000100140x00010018
C++int a;double f;Vehicle c,d;a = 10;c.wheelCount = 4;d = c; // gets copy of cd.wheelCount = 6;
af
c
d
0x0001001c
…
0x00010034
…
Javaint a;double f;Vehicle c,d;a = 10;c = new Vehicle;d = c; // d is synonym of cd.wheelCount = 4;
0x000100100x000100140x00010018
afc 0x0001001cd 0x00010020
0x0ffff5020
0x0ffff50200x0ffff5020
MyClass object?
Heap Stack
Stack
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 11
Level of Indirection – == C++int a,b; Vehicle c,d;…if (a==b) {…}…if (c==d) {…}
c
d
0x0001001c
…
0x00010034
…
Javaint a,b; Vehicle c,d;…if (a==b) {…}…if (c==d) {…}…if (c.equals(d)) {…}
0x000100100x000100140x00010018
ab
c 0x0001001cd 0x00010020
0x0ffff5020
0x0ffff50200x0ffff5020
MyClass object?
Heap Stack
Stack
defined in Vehicle class
e
0x000100100x00010014
abe 0x00010018
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 12
Level of Indirection – pass by value
0x000100100x000100140x00010018
C++…void foo(Vehicle v, int i) {v.wheelCount=0;i=10;}…int a,b; Vehicle c,d;…foo(c,a)
af
c
d
0x0001001c
…
0x00010034
…
Java…void foo(Vehicle v, int i) {v.wheelCount=0;i=10;}…int a,b; Vehicle c,d;…q.foo(c,a)
0x000100100x000100140x00010018
afc 0x0001001cd 0x00010020
0x0ffff5020
0x0ffff50200x0ffff5020
Vehicle object?
Heap Stack
Stack
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 13
Pointers
• What are they?• Pointer arithmetic• Dynamic allocation: new, delete• Relation to C++ arrays (non-dynamic allocation)• Dynamic allocation - arrays: new[], delete[]• Pointers and pass-by-value• NULL
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 14
Pointer Type• stores an address of another object• syntax
– declaration typename *variableName;
– address-of operator: &– pointer dereference operator:
*varName(*varName).memberName varName->memberName
C++int a; int* pi;Vehicle c; Vehicle* pv;pi = &a;*pi = 10;pv = &c;pv->move(NORTH,5)c.move(NORTH,10)
0x000100100x000100140x00010018
api
c
pv
…
0x00010020
…
Stack
0x00010010
0x00010018
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 15
Pointer Type - = and ==int a,b; int *pi,*pj;Vehicle c,d; Vehicle *pv1,*pv2;pj = pi = &a;pv1 = &c;pv2 = &d;
if (pj == pi) {…}…if (pv1 == pv2) {…}…if (*pj == *pi) {…}…if (*pv1 == *pv2) {…}
0x10
0x18
a
c
pi
Stack
0x100x14b
0x1cpj0x20
d 0x38
pv2pv1 0x50
0x54
0x10
0x200x38
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 16
pv2
Dynamic allocation/deallocation: new and delete C++int* pi;Vehicle *pv1,*pv2;pi = new int;pv1 = new Vehicle;pv2 = new Vehicle;*pi = 10;pv1->move(NORTH,10);pv2->move(EAST,15);…delete pv1;…delete pv2;…delete pi;
0x000100100x000100140x00010018
pipv1
Stack …..
0xffff5020
0xffff5020
Heap
?
0xffff5030
?
Vehicle object
0xffff5030
…..
…..
?
0xffff5060
Vehicle object
0xffff5040
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 17
C++ Pointers – Address is accessible
• In other languagespointer is an opaque type. In C++, access as numeric value is possible.
C++int a,b;int* pi;pi = &a;*pi = 10;cout << (unsigned int)pi << endl;
C++int* pi;pi = reinterpret_cast<int*>(0x0000ffff);*pi = 10;
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 18
C++ - Address Arithmetic
• add an integer to apointer to get newpointer
• subtract pointer from pointer to get integer
• Pointer arithmetic takes into account size of pointed to type!
C++char a[10]="hello";char *p1, *p2;for (p1 = p2 = &a[0]; *p2 != '\0‘; p1 += 1, p2 += 2) cout << *p1 << ‘ ‘ << *p2 << endl;
C++char a[10]="hello";char *p1, *p2;p1 = &a[0]; p2 = &a[9];cout << (int)(p2-p1) << endl;
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 19
…int two[2],ten[10];int *pi; *(ten+9) = 9;// same as ten[9] = 9;pi = ten; // cast int[X] to int*,OK!*pi = 0;for(i=1;i<=8;i++)
ten[i]=i;for(pi=&ten[1]; pi != &ten[9]; pi++)
(*pi)++;// two = pi; casting int* to
int[X] illegal
C++ Arrays• C++ arrays and pointers are closely related
– a typename[X] can be type cast to a typename*
0x100x14
a
pi
ten
0x3C
…
two0x44 0x14
Stack …..
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 20
Dynamic arrays: new[] and delete[] C++int four[4];int* pi;pi = new int [7];…delete[] pi;
0x10four
pi
Stack …..
Heap
?
0xffff5030
int[7]
…..
…..
0x20 0xffff5030
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 21
NULL
• How to indicate that a pointer points to nothing?
C++int a;int* pi=NULL;*pi = 10; // run-time error…pi = &a;*pi = 10; // OK…pi = new int;*pi = 10; // OK…delete pi;pi=NULL; // good practice!
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 22
Pointers + pass-by-value = output parameter
• Function parameters are pass by value – to change the actual parameter, pass pointer to target variable and in function dereference pointer to change target variable
C/C++void upperCase(char* pc) {
if (isalpha(*pc))*pc = *pc - 'a' + 'A';
} …char a[10]="Hello"; int i;for (i=0;a[i]!='\0';i++)
upperCase(&a[i]);
C++ programmersdon’t use pointers
for output arguments.
See C++ Reference (#27)
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 23
Linked List Example
class List {class Node { char text[10];
Node* next;void printAll(void);};
List(); Node* head; void print(void); };
List::List () {head=NULL;}void List::print() { if (head != NULL) head->printAll();}void List::Node::printAll(void)
{cout << text << endl;if (next != NULL) next->printAll();}
List.h
List.cpp
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 24
Destructor
class List {class Node { Node* next;
}; ~List(); Node* head;};
List::~List () { Node* n; for (n=head;n!=NULL;n=n->next)
delete n; }
List.h
List.cpp
• destructor – (~classname()) automatically called when object is deallocated (either automatically or via delete)
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 25
Function Pointer
• Function Pointer - holds address of function’s first machine instruction– rettype (*pointerVarName)(type,type,...);– dereferencing syntax: same as a function call– address arithmetic not relevant
void doItTenTimes(int (*funcPtr)(int), int ten[10]) { for (int i=0;i<10;i++)
ten[i] = funcPtr(ten[i]) }int plusone(int i) { return i+1;}int minusone(int i) { return i-1;}…{
int ten[10];doItTenTimes(plusone,ten);doItTenTimes(minusone,ten);
}
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 26
Function Pointer example
void List::Node::traverseAll(NodeFunction nf) { nf (text); if (next!=NULL) next->traverseAll(nf); }void SayHello (char text[]){cout << "Hi" << text …;}void SayGoodbye (char text[]) {cout << “Bye" << text …;}…{
List list;… make a list …list.traverse(SayHello);list.traverse(SayGoodbye);
}
class List { typedef void (*NodeFunction) (char text[]); class Node { char text[10];
Node* next;void traverseAll (NodeFunction nf);};
void traverse(NodeFunction nf); };
List.h
List.cpp
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 27
C++ Reference – typename &• Not present in C; similar to pointer but
– no dereference operator needed (nor possible) – reference can only be initialized to reference another
variable; it can’t be assigned a new referent later on– use reference function parameter instead of pointer for
output function parameter and for polymorphism• denoted by: typename & variable;
void upperCase(char& pc) {if (isalpha(pc))
pc = pc - 'a' + 'A';}
…char a[10]="Hello";for (i=0;a[i]!='\0';i++)
upperCase(a[i]);
compare to slide #22
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 28
C++ polymorphism – (1)
• method invocation – only polymorphic on pointers or referencesclass Shape { virtual void draw(); };
class Circle { void draw(); };
Shape s1,*s2;Circle c1;c1.draw(); // Circle::draws1.draw(); // Shape::draw
if (makeCircle) s2 = new Circle();else s2 = new Shape();// Circle::draw or Shape::draws2->draw();
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 29
C++ polymorphism – (2)
• method invocation – only polymorphic on pointers or referencesvoid foo (Shape s1, Shape& s2) { s1.draw(); // Shape::draw // Circle::draw or Shape::draw s2.draw(); }
class Shape { virtual void draw(); };
class Circle { void draw(); };
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 30
C++ polymorphism - virtual
• class method is only polymorphic if the base class declares them as virtual; otherwise overriding a method in derived class will not be polymorphic
class Shape { virtual void draw(); };
class Shape { void draw(); };
class Circle { void draw(); };
class Circle { void draw(); };
if (makeCircle) s2 = new Circle();else s2 = new Shape();// always Shape::draws2->draw();
if (makeCircle) s2 = new Circle();else s2 = new Shape();// Shape::draw || Circle::draws2->draw();
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 31
How pointer bugs manifest themselves - ‘Memory Errors’
• Memory Leaks• Memory Access Errors - C/C++ won’t protect
programmer from stomping on random memory locations! (C++ - "Yes, Sir!")– Invalid Array Index– Bad Pointer I– Bad Pointer II– Bad Pointer III– Bad Pointer IV– …
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 32
Memory Leaks• memory leak – program does not execute
a delete for each new
int four[4];int* pi;pi = new int [7];…// forgot delete[] pi;return;
0x10four
pi
Stack …..
Heap
?
0xffff5030
int[7]
…..
…..
0x20 0xffff5030
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 33
Memory Error: Invalid Array Index
C++…int two[2],ten[10];int *pi; *(ten+9) = 9; // same as ten[9] = 9;pi = ten;*pi = 0;for(i=1;i<=15;i++)
ten[i]=i;for(pi=&ten[1]; pi != &ten[9]; pi++)
(*pi)++;// two = pi; casting int* to
int[X] illegal
0x100x14
a
pi
ten
0x3C
…
two0x44 0x14
Stack …..
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 34
Memory Error: Bad Pointer I – overwrite local variable
C++…int two[2],ten[10];int *pi; *(ten+9) = 9; // same as ten[9] = 9;pi = ten;*pi = 0;for(i=1;i<=9;i++)
ten[i]=i;for(pi=&ten[1]; pi != &ten[15]; pi++)
(*pi)++;// two = pi; casting int* to
int[X] illegal
0x100x14
a
pi
ten
0x3C
…
two0x44 0x14
Stack …..
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 35
Memory Error: Bad Pointer II – overwrite stack frame
0x100x14
a
pi
ten
0x3C
…
two0x44 0x14
Stack
What if call frame puts IP and FP here?
IPFP
C++…int two[2],ten[10];int *pi; *(ten+9) = 9; // same as ten[9] = 9;pi = ten;*pi = 0;for(i=9;i>=-10;i--)
ten[i]=i;for(pi=&ten[1]; pi != &ten[9]; pi++)
(*pi)++;// two = pi; casting int* to
int[X] illegal
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 36
pv2
Memory Error: Bad Pointer III – overwrite reallocated heap memory
C++int* pi;Vehicle *pv1,*pv2;pi = new int;pv1 = new Vehicle;*pi = 10;…delete pv1;…pv2 = new Vehicle;…// YIKES!pv1->wheelCount = 4;
0x000100100x000100140x00010018
pipv1
Stack …..
0xffff5020
0xffff5020
Heap
?
0xffff5030
?
Vehicle object
0xffff5030
…..
…..
0xffff5030
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 37
pv2
Memory Error: Bad Pointer IV – overwrite internal heap data structures (Super YIKES!)
C++int* pi;Vehicle *pv1,*pv2;pi = new int;pv1 = new Vehicle;*pi = 10;…delete pv1;…delete pi;…pi = new int [30];…// YIKES!pv1->wheelCount = 4;
0x000100100x000100140x00010018
pipv1
Stack …..
0xffff5020
0xffff5020
Heap
?
0xffff5030
?
Vehicle object
0xffff5030
…..
…..
0xffff5030
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 38
In general with memory errors ….
• careless coding can change memorylocations (and hencevariables) you didn’twant to change
Errors can show upmuch later…
C++char a[10]="Hello"; // missing '!‘int i=5;char b[10]="Goodbye!";char *pa=&a[0];while(*pa != '!')
{upperCase(pa);pa++;} … do other stuff …i += 5;cout << i << endl;
©Zachary Wartell, UNCC 9/28/2006 11:30 AM 39
Revisions
• Revision 1.0:• Revision 1.1: spelling and syntax typos• Revision 1.2: added diagram that I drew by hand in class, slide 5• …way to tedious to keep this up … see SVN logs…