430 likes | 605 Views
Dynamic Allocation. Chapter 19 Section 19.4 This file is called Mike-Ch19.ppt. Outline. We will learn how to allocate dynamic (that is, runtime-controllable) amounts of memory in C This will basically be making dynamically sized arrays. Dynamic Allocation.
E N D
Dynamic Allocation Chapter 19 Section 19.4 This file is called Mike-Ch19.ppt
Outline • We will learn how to allocate dynamic (that is, runtime-controllable) amounts of memory in C • This will basically be making dynamically sized arrays
Dynamic Allocation • Used when space requirements are unknown at compile time. • Most of the time the amount of space required is unknown at compile time. • Example • Need space to allow user to enter some data • 80 bytes? 132? 1? 256? 255? • Three Friends • malloc • realloc • free
Every time a C programmer uses malloc incorrectly, a kitten explodes Only your C skills can save me! Picture CC license http://www.flickr.com/photos/fieldsphotos/128177546/
Mike’s Kitten Saving Challenge • I count 16 different common ways to screw up malloc in this lecture • Use the paper I’ve given you, and write down every one you can find as we go • I am absolutely not kidding when I tell you that a malloc bug can waste numerous programmer-weeks 0
malloc int *ip; ip = malloc(10 * sizeof(int)); if(ip == NULL) { /* Handle Error! */ } • Options for handling error • Abort • Ask again • Save user data • Ask for less • Free up something 1
malloc int *ip; ip = malloc(10 * sizeof(int)); if(ip = NULL) { /* Handle Error! */ } • Note how incredibly bad it would be to use the assignment operator! • The pointer would be set to NULL • The error code would be skipped • Some programmers use: NULL == ip 2
malloc -- What happens? int foo(int n) { int *ip; ip = malloc(n * sizeof(int)); if(ip == NULL) { /* Handle Error! */ } ... Stack Heap 40 bytes Data Code
Anticipating Problems ip = malloc(10 * sizeof(int)); if(ip == NULL) • What might go wrong? • Be paranoid!
Welcome to my nightmare! ip = malloc(10 * sizeof(int)); Code foolishly inserted here! if(ip == NULL) • Be afraid. • Be very afraid! 3
Tricky but safe if((ip = malloc(10*sizeof(int))) == NULL) { /* Handle Error Here */ }
Using the space int sample(int n) { int i; int *ip; if((ip = malloc(n*sizeof(int))) == NULL) { /* Handle Error Here */ } for(i = 0; i < n; i++) ip[i] = 0; ...
Flexibility #define MAX 10 int *ip; ip = malloc(MAX * sizeof(int)); • What if we change the type of int *ip??? #define MAX 10 int *ip; ip = malloc(MAX * sizeof(*ip)); 4
After some calls to malloc Stack Heap Non-constant data Constant data Code
Address 1400 2400 3000 4000 Size 200 300 100 500 What does runtime track? Notice that no record is made of the name of any pointer
What happens? int *ip; ip = malloc(...); . . . free(ip);
Prototypes void *malloc(size_t n); void free(void *p); void *realloc(void *p, size_t n); • What is this mysterious void pointer?
void pointer • Not originally in c • Relatively recent addition • Basically a “generic” pointer • Intended for use in applications like free where the block of memory located at some address will be freed without any necessity of defining the type
Powerful & Dangerous void *vp; char *cp; int *ip; ip = cp; /* illegal */ • Instead ip = (int *)cp; • Or vp = cp; /* Legal, powerful and */ ip = vp; /* dangerous!!! */ • Why is this being done? 6
ip cp Casting • Usually casting is not required • May be masking a problem int *ip; char *cp; ... *cp = ‘x’; *ip = ??? *ip = 42; *cp = ???
Warnings • Using void pointers as a crutch to get around casting is a “bad” thing! • Malloc doesn’t care what you are doing with a block of memory it allocates to you. What you do with the memory is your responsibility • Passing in non-malloced values to free is a bad thing! • Free does not change contents of block that was freed • Free does not change pointer • After a call to free it is possible to do anything to the freed memory that was possible before the call!!! • Definitely a bad thing!!! 6 7
Persistent Data I char *foo(void) { static char ca[10]; return ca; } • Anyone calling this function now has access to this block. Could be dangerous. Why? • Note that this approach is not dynamic
Example char *strFromUnsigned(unsigned u) { /* this is the important part */ static char strDigits[] = “?????”; char *pch; pch = &strDigits[5]; /* you can trust us that this really will convert an unsigned to a string */ do *--pch = (u % 10) + '0'; while((u /= 10) > 0); return pch; }
Problem in use strHighScore = strFromUnsigned(HighScore); . . . strThisScore = strFromUnsigned(ThisScore); 8
Persistent Data II char *foo(void) { char ca[10]; return ca; } • Since ca was allocated on stack during function call pointer returned is now pointing to who knows what • Bad 9
Persistent Data III char *foo(void) { char *ca = malloc(...); /* error checking but no free */ return ca; }
Memory Leaks • Memory leaks occur when the programmer loses track of memory allocated by malloc or other functions that call malloc void foo(void) { char *ca = malloc(...); /* no free */ return; } • Bad 10
Memory Leaks • Obviously a program that runs for a fraction of a second and then terminates will not cause a problem if it leaks a few bytes of memory. • However, for real world programs memory leaks are not acceptable. • For the educational purposes of this class your programs will be required to leak no memory! • Programs submitted with memory leaks may incur severe penalties.
Memory Management • Some functions that call malloc • calloc • strdup • regcmp • others... • C doesn’t do automatic memory management for efficiency reasons • If you want to manage memory...do it yourself!
Memory Management • Ok? int *ip, *ip2; ip = malloc(...); ip2 = ip; free(ip); *ip2 = 42; • Yes • No • Maybe
Memory Management • Ok? int *ip, *ip2; ip = malloc(...); ip2 = ip; free(ip); *ip2 = 42; • Yes • No • Maybe 11
More... int *ip, *ip2; /* Line 1 */ ip = malloc(...); /* Line 2 */ /* Error checking here */ ip2 = ip; /* Line 3 */ ip += 4; /* Line 4 */ free(ip); /* Line 5 */ free(ip2); /* Line 6 */ Problem line? 13 12
Realloc ptr = realloc(ptr, num_bytes); • What it does (conceptually) • Find space for new allocation • Copy original data into new space • Free old space • Return pointer to new space
ptr Realloc ptr in-use Before in-use After
ptr Realloc: What might happen Before ptr unused After
Dynamic Allocation int *ip = malloc(...); • malloc may allocate more space than requested • Why? • Efficiency • Typically if you ask for 1 byte you will get 8. • Given this line of code char *cp = malloc(1); • Which is more likely • Program will probably keep this memory as is • Program will eventually realloc • How much can you safely use?
Safety • Program should only use memory actually requested • Big problem! Why? • Program that oversteps bounds may work... • Sometimes! • Note... char *cp = malloc(1); • ADDR SIZE • cp 8 (maybe!) • Now... realloc(cp,6); • will return same pointer thus... 14
Realloc • May return same pointer passed to it without indicating any problem. • Using memory beyond that which has been allocated may work • Some of the time • Normally it will work when tested by a student but will fail when tested by a TA (for a grade) • Go figure • Thus the “No Mercy” rule
Realloc • Realloc may return • same pointer • different pointer • NULL • Is this a good idea? cp = realloc(cp, n); • Yes • No • Sometimes
Realloc • Is this a good idea? cp = realloc(cp, n); • No! • If realloc returns NULL cp is lost • Memory Leak! 15
How to do it void *tmp; if((tmp = realloc(cp,...)) == NULL) { /* realloc error */ } else { cp = tmp; free(tmp); } NO! 16
Additional Information • realloc(NULL, n) malloc(n); • realloc(cp, 0) free(cp); • These can be used to make realloc work in a single loop design to build a dynamic structure such as a linked list.