270 likes | 344 Views
System Programming. Practical Session 7. C++ Memory Handling. Memory Model There are two "kinds" of memory available to a process: Stack Rather small temporary storage for function-local data. Heap Big storage for data.
E N D
System Programming Practical Session 7 C++ Memory Handling
Memory Model • There are two "kinds" of memory available to a process: • Stack Rather small temporary storage for function-local data. • Heap Big storage for data. • Note that every variable you declare inside a function lives on the stack. • Once you leave the scope of the function, the stack variables are discarded.
Memory Model int add(int first, int second){ int result; result = first + second; return result; } int main(){ int a = 5, b = 3,sum; sum = add(a,b); } heap stack
Memory Model int add(int first, int second){ int result; result = first + second; return result; } int main(){ int a = 5, b = 3,sum; sum = add(a,b); } heap stack sum b a 3 5
Memory Model int add(int first, int second){ int result; result = first + second; return result; } int main(){ int a = 5, b = 3,sum; sum = add(a,b); } heap stack result second first 8 3 5 sum b a 3 5
Memory Model int add(int first, int second){ int result; result = first + second; return result; } int main(){ int a = 5, b = 3,sum; sum = add(a,b); } heap stack sum b a 8 3 5
Pointers • Pointers are variables whose values are memory locations - • addresses of some data • Java references • Strings1 =newString("astring"); • String s2 = s1; • s1 =null;
C++ pointers • //Declaring a pointer: • int*p_j; • float*p_f; • //Accessing the values of a pointer: • 3. intj=5; • 4. p_j=&j; • 5. std::cout<<p_j<<std::endl; • 6. std::cout<<*p_j<<std::endl; • // output: 0x22ccc4 • // 5
C++ pointers • Example of bad assigning to pointers • int*p_i=(int*)923451; • std::cout<<p_i<<std::endl; • std::cout<<*p_i<<std::endl;
The operators & and * • & • The address of the given variable. • * • The variable of the given address. • In declaration: means that this variable is a pointer. int j; int * p_j; p_j = &j; *p_j = 10;
Comparing pointers • intj=5; • inti=5; • int*p_j=&j; • int*p_j2=&j; • int*p_i=&i; • if(p_j==p_j2){std::cout<<"1 ";} • if(p_j==p_i){std::cout<<"2 ";} • if(p_j!=p_i){std::cout<<"3 ";} • if(*p_j == *p_i){std::cout<<"4 ";} //output: 1 3 4
Pointers to pointers • inti=5; • int*p_i=&i; • int**pp_i=&p_i; • std::cout << pp_i << std::endl; • std::cout << *pp_i << std::endl; • std::Cout << **pp_i << std::endl; //output: 0x151bb84 // 0x151bb90 // 5
Pointers Arithmetic The operations addition and subtraction are defined for pointers. + , - , += , -= , ++ , -- • intj=5; • int*i=&j; • std::cout<<"i="<<i<<std::endl; • i+=1; • std::cout<<"i+1="<<i<<std::endl; • // output: i = 0x22ccc4 • // i+1 = 0x22ccc8
Arrays Arrays in C++ are just special pointers. Declaration: int A[10]; • A memory block big enough for holding 10 integers (10*sizeof(int)) is allocated on the stack • A holds the address of the start of this block. • The address A holds can’t be changed: • A = A + 1; // compilation error.
Stack address Arrays Arrays in C++ are just special pointers. A[0] 1916 A[1] 1920 A[9] 1952 1956 Declaration: int A[10]; • A memory block big enough for holding 10 integers (10*sizeof(int)) is allocated on the stack • A holds the address of the start of this block. • The address A holds can’t be changed: • A = A + 1; // compilation error.
Stack address Arrays Arrays in C++ are just special pointers. A[0] 1916 A[1] 9 1920 A[9] 1952 j 9 1956 int j; int A[10]; A[1] = 9; j = A[1]; //*(A + 1) = 9; //j = *(A + 1);
Use of regular pointers as arrays • doubleA[10]; • ints=0; • double*pi; • doublej; • pi=&j; • pi[3]=5;//BAD! • pi=A; • pi[3]=5;//OK. • pi++; • pi[0]=1;
string representation using char * A string can be represented as array of chars terminating with 0. c[0] ‘a’ c[1] ‘b’ c[2] ‘c’ c[3] ‘d’ c[4] ‘e’ c[5] ‘f’ c[6] ‘g’ c[7] 0 • char*c="abcdefg"; • std::cout<<c<<std::endl; • std::cout<<c[3]<<std::endl; • std::cout<<&(c[3]); • // output abcdefg • // d • // defg
Converting from string to char * and back • std::strings=std::string("abcdefg"); • const char*cs=s.c_str(); • std::strings2=std::string(cs);
Using command line arguments #include <iostream> #include <string> using namespace std; int main(int argc, char **argv) { cout << "Program name: " << argv[0] << endl; cout << "Number of paramters: " << (argc - 1) << endl; if (argc > 1) { cout << "Parameters: " << endl; for (int i=1; i<argc; ++i) { cout << "\t" << string(argv[i]) << endl; } } return 0; }
Memory Handling new - allocates memory on the heap, initializes it and returns a pointer to it. • int*i=new int; • int*i2=newint(2); • String*s=new string("I'montheheap”); • if(0==s){//handle allocation error} • std::cout<<"s="<<s<<std::endl; • std::cout<<"s="<<*s<<std::endl; • deletes; All memory allocated by new must be freed using delete
Arrays on the heap A block of memory is allocated using new[ ]. • int*A=newint[10]; • int*B=A+1; • A[0]=1; • A[1]=2; • B[1]=3; • delete[]A;
Safe delete Delete only what has been allocated by new and hasn’t been deleted yet. • //First, ensure that p points to a storage allocated by new. • // Then use the following. • if(0!=p){ • deletep; • p=0; • }
Pointer Dangers • Uninitialized pointers • int*p; • *p=3;//bad! • Dereferencing a null pointer • int*p=0; • *p=3;//bad! • Dereferencing a deleted pointer • int*p=newint; • deletep; • *p=5;//bad!
Pointer Dangers • Dereferencing a dangling pointer • int*p,*q; • p=newint; • q=p; • deleteq; • *p=3;//bad!
Memory leak int *ar = new int[1000]; ……….. //some use of ar, but no delete ar = new int[235]; Correction: int *ar = new int[1000]; ……….. if (0 != ar) delete[] ar; ar = new int[235];
Concluding Example #include <iostream> #include <string> using namespace std; void f1() { string s("I will die young"); cout << s << endl; } void f2() { string* p_s = new string("I will survive!"); cout << *p_s << endl; } void f3() { string* p_s = new string("I will be murdered"); cout << *p_s << endl; delete p_s; } void f4() { string* p_s = new string("I'll die and take everyone with me"); cout << *p_s << endl; delete p_s; delete p_s; cout << "this line is never reached" << endl; return; } int main() { f1(); f2(); f3(); f4(); }