CS110_07b_ptrMemory - EECS110: 7b Pointers & Memory...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: EECS110: 7b Pointers & Memory Jack Tumblin jet@cs.northwestern.edu . (Recall) static Keyword static int i; static double arr[5]; static void setKey(int *a); // put before data type // OK for arrays & ptrs // and functions. WEIRD! (at least) 2 meanings: 1) "only accessible from inside this module", or (`module' is one .c file and it's .h file interface) Sets scope for functions; can't call them from interface And for `global' variables, `global' arrays (See pg. 359, 410) 2) "Always keep this named memory valid" Use for local variables, declared within a function DIFFERS from global variable; name can STILL go out-of-scope But pointers to it (set when name was in-scope) always work! (Recall) static Example int* magic_num(int strt); // prototype int main(void) { int i=0, *pI; // ptr to integer pI = magic_num(i); printf("random 4fib=%d\n",*pI); return 0; Result: } int* magic_num(int strt) { static int keep[9] = {0,1,2,3,5,8,13,21,34}; int *pOut; pOut = keep+(strt+rand()%4)%9; keep array stays valid in memory, but return(pOut); } strt and pOut do not. pI >random 4fib=3 > (Recall) Arrays vs. Pointers An array resides in a named block of memory. Array size is constant: fixed when program is written. int list[4]; list d n 0 0 0 3 z p 0 0 0 1 0 0 0 6 0 0 0 4 0 0 0 8 j list[0] list[1] list[2] list[3] Pointers p1 can point to blocks of memory (like a movable array name) but have no elements of its own. how can they get their own memory blocks to control? What if you want to vary array size, or want to choose size array size after the program starts running? (at `run time'?) Dynamic Allocation Dynamic Allocation == memory taken and/or released during execution. Dynamic Allocation enables us to : claim a computed # of elements at run time (function: malloc) malloc release all elements you reserved (function: free) free Less important variants (OK to ignore them) can: change the number of elements (function: realloc) realloc claim already-zero-valued memory (function: calloc) calloc Not worth using--slow, inflexible. Write your own... Dynamic Allocation: The `Get Memory' Function void* malloc(int size); Returns ptr. to byte 0 of the newly-reserved block of memory. void* return type means `pointer to unknown type'. You are REQUIRED to use a typecast before assigning it to any pointer. Find this malloc()fcn. malloc() prototype in stdlib.h The total number of bytes that we want to allocate. ( Use the sizeof() function to find the size of a type). Dynamic Allocation: The `Done with Memory' Function void free(void *pMemBlock); free() has no return value. It only releases memory that was reserved earlier by by malloc(). () Pointer to byte 0 of a prev. allocated memory block. Find this free() function prototype in stdlib.h IMPORTANT: IMPORTANT Never free()memory that was never malloc()'d. free() malloc() Always free()memory that was malloc()'d earlier. free() malloc() If you forget, your program will grow larger and larger and may eventually fill all memory: `memory leak' BAD! leak Dynamic Allocation: Example #include<stdio.h> #include<stdlib.h> int main ( ) { malloc(),free()are found in stdlib.h int *pStart, size; printf("Type the size: "); scanf("%d", &size); pStart = (int *) malloc (size * sizeof(int)); // other operations here free(pStart); // more on that later return 0; } Dynamic Allocation: Example #include<stdio.h> #include<stdlib.h> pointer-to-int int main ( ) int { 900: pStart: junk 904: size: junk 908: int *pStart, size; printf("Type the size: "); 912: scanf("%d", &size); 916: pStart = (int *) malloc (size * sizeof(int)); 920: // other operations here 924: free(pStart); // more on that later return 0; } Dynamic Allocation: Example #include<stdio.h> #include<stdlib.h> int main ( ) { 900: pStart: junk 904: size: 3 The user types in 3 908: int *pStart, size; printf("Type the size: "); 912: scanf("%d", &size); 916: pStart = (int *) malloc (size * sizeof(int)); 920: // other operations here 924: free(pStart); // more on that later return 0; } Dynamic Allocation: Example #include<stdio.h> malloc will: #include<stdlib.h> 900: pStart: 908 --Find, reserve a 12 byte memory block, int main ( ) pointer to that block. --Return a 904: size: 3 { junk It returns the address of the 0th byte reserved. 908: int *start, size; (we assign the address to pointer pStart) junk printf("Type the size: "); 912: scanf("%d", &size); junk 916: pStart = (int *) malloc (size * sizeof(int)); 920: // other operations here sizeof(int) returns the size of 924: free(pStart); // more on that later one int variable. On Windows return 0; machines, an int is 4 bytes long. int } Dynamic Allocation: Example #include<stdio.h> #include<stdlib.h> int main ( ) { 900: pStart: 908 904: size: 3 15 908: int *pStart, size; printf("Type the size: "); 28 912: scanf("%d", &size); 40 916: pStart = (int *) malloc (size * sizeof(int)); 920: // other operations here 924: *pStart = 15; free(pStart); // *(pStart+1) later more on that = 28; *(pStart+2) = *(pStart+1) + 12; return 0; } Dynamic Allocation: Example #include<stdio.h> #include<stdlib.h> int main ( ) { 900: pStart: 908 904: size: 3 908: int *pStart, size; printf("Type the size: "); 912: scanf("%d", &size); 916: pStart = (int *) malloc (size * sizeof(int)); 920: // other operations here 924: Release the reserved block of memory. free(pStart); // more on that later DANGER! don't use the block anymore! return 0; Entirely invalid and might be assigned to other } variables and other uses... Dynamic Allocation - malloc The Right Way to use malloc: malloc int *pScores; pScores = (int *)malloc(8 * sizeof(int)); typecast: a 'void' pointer. Make it the right kind of pointer (int, char ,etc.) malloc() returns Dynamic Allocation - malloc The Right Way to use malloc: malloc int *pScores; pScores = (int *)malloc(8 * sizeof(int)); typecast: a 'void' pointer. Make it the right kind of pointer (int, char ,etc.) malloc() returns Use sizeof() to find the number of bytes: Different computer types may use different sizes for each data type (e.g.int isn't always 4 bytes). Do not assume it in your programs. Dynamic Allocation - malloc The Wrong Way to use malloc: malloc int *pScores; pScores = malloc(32); BAD IDEA!! ? Why ? Dynamic Allocation - malloc The Wrong Way to use malloc: malloc int *pScores; pScores = malloc(32); BAD IDEA!! !! Missing typecast !! Even though some robust compilers may figure it out, robust programs always assume that they can't; don't skip this cast. Dynamic Allocation - malloc The Wrong Way to use malloc: malloc int *pScores; pScores = malloc(32); BAD IDEA!! Specific number of bytes!! !! Missing typecast !! Even though some compilers may figure it out, robust programs always assume that they can't. How many ints can fit int into this block of memory? Not all machines use 4 bytes for int. Do not assume it in int your programs. Dynamic Allocation - malloc If malloc() can't get requested memory, it returns NULL (address 0) NULL: a valid memory address that NEVER holds valid data. data Good programming practice: Always check whether malloc() returned NULL: char *pMsg; pMsg = (char *) malloc (20 * sizeof(char)); if (pMsg == NULL) { printf("Insufficient memory. Error Exit\n"); return -1; } Dynamic Allocation - free free() ignores pointer names--it names uses only the address stored as the pointer's value. Any pointer name is OK if it points to byte 0 of the memory block reserved by malloc(). () char *pMsg, *pWord, aLetter = `A'; pMsg = (char *) malloc (20 * sizeof(char)); // reserve a memory block pWord = pMsg; // another pointer to block pMsg = &aLetter; // pMsg now points to letr free(pWord); // free the memory block Dynamic Allocation - free CAREFUL : Never deallocate the same memory twice! A commonplace misteak--unpredictable results: char *pMsg, *pWord, aLetter; pMsg = (char *) malloc (20 * sizeof(char); pWord = pMsg; // both point to same byte 0 strcpy(pWord, "Welcome!\n"); // use the memory ... free(pMsg); // Free the memory. free(pWord); // RUNTIME ERROR! No block to free! Cautions for malloc(), free() free(ptr)is dangerous if ptr is invalid!! Unpredictable: nothing, spurious bug, crash, or ... ? Programs that allocate memory but never release it have `memory leaks' Programs gets larger and larger as they run Eventually, these programs MUST stop or crash! Best avoided by orderly programming habits: BEST: Keep malloc/free pairs in same block of code GOOD: One central `garbage collection' function BAD: Scattered, conditional malloc(), () scattered, conditional free(). IMPORTANT NOTE: All dynamically allocated blocks of memory reserved by malloc() are always static. static These memory blocks are: always valid, always reserved, never changed or re-used for other purposes, until it is de-allocated by free() (and then you MUST assume it is gone forever!) (Something is there in memory, but you can never trust it) Dynamic Allocation: Example #include <stdlib.h> malloc() and free() are int main(void) defined in stdlib.h { int k,kmax,*pKey,*pDone; ... pKey = (int *)malloc( kmax*sizeof(int) ); if(NULL==pKey) return(-1); // Error!?!?! for(k=0; k<kmax; k++) malloc(n) function: { pKey[k] = rand(); reserve a block of n bytes } (Block has no name) ... (more work with pKey) ... pDone = pKey; free(pDone); } free(ptr) function: release a block of bytes at address ptr. ptr ...
View Full Document

This note was uploaded on 10/05/2011 for the course COMPUTER S 110-1 taught by Professor Tumblin during the Spring '11 term at Northwestern.

Ask a homework question - tutors are online