330 likes | 415 Vues
Lecture 16: Pointers and Memory Management. Joel Winstead http://www.cs.virginia.edu/~jaw2u. CS201j: Engineering Software University of Virginia Computer Science. Menu. Null Pointers in C Memory Management in C Phylogeny Revisited. Pointers in C.
E N D
Lecture 16: Pointers and Memory Management Joel Winstead http://www.cs.virginia.edu/~jaw2u CS201j: Engineering Software University of Virginia Computer Science
Menu • Null Pointers in C • Memory Management in C • Phylogeny Revisited CS 201J Fall 2002
Pointers in C • Pointers are similar to object references in Java • Assigning a pointer has sharing semantics int i = 37; int *p = malloc(sizeof(int)); int *q; q = p; *p = 7; 37 i 7 p q CS 201J Fall 2002
Null Pointers • What if a pointer doesn’t point to anything? void main(String argv[]) { Integer i = null; System.out.println(i.intValue()); } int main(int argc,char *argv[]) { int *i = NULL; printf(“i is %d\n”,*i); } CS 201J Fall 2002
Null Pointers • What if a pointer doesn’t point to anything? void main(String argv[]) { Integer i = null; System.out.println(i.intValue()); } int main(int argc,char *argv[]) { int *i = NULL; printf(“i is %d\n”,*i); } Exception in thread “main” java.lang.NullPointerException at nullref.main(nullref.java:7) Behavior is undefined! CS 201J Fall 2002
Following Null Pointers • The program may crash immediately • The program may produce corrupted output • The program may corrupt data somewhere else in the program’s memory • This results in a difficult-to-find bug • The program could mail itself to everyone in your address book and cause your computer to self-destruct • The C standard does not define what should happen, so absolutely anything is legal! CS 201J Fall 2002
Splint Annotations for Pointers • /*@notnull@*/ • A pointer guaranteed not to be null • /*@null@*/ • A pointer that might be null /*@null@*/ FILE * fopen(/*@notnull@*/ char *filename,char *mode); CS 201J Fall 2002
Splint Warnings • Splint reports a warning if: • The program dereferences a /*@null@*/ pointer without checking first • The program assigns a /*@null@*/ pointer to a /*@notnull@*/ variable • The program passes a /*@null@*/ pointer to a function expecting a /*@notnull@*/ pointer CS 201J Fall 2002
Example char firstChar( /*@null@*/ char *s) { return *s; } > splint null.c Splint 3.0.1.6 null.c: (in function firstChar) null.c:3:11: Dereference of possibly null pointer s: *s null.c:1:35: Storage s may become null Finished checking --- 1 code warning found CS 201J Fall 2002
Correcting the Problem char firstChar( /*@null@*/ char *s) { if (s == NULL) { fprintf(stderr,”s is null in firstChar\n”); exit(EXIT_FAILURE); } else { return *s; } } CS 201J Fall 2002
Another Solution char firstChar( /*@notnull@*/ char *s) { return *s; } CS 201J Fall 2002
malloc • Memory in C is allocated using the malloc function • This is similar in some ways to Java’s new operator • We use sizeof to determine how much memory to allocate int *i = malloc(sizeof(int)); char *s = malloc(sizeof(char)*100); Species s = malloc(sizeof(*s)); CS 201J Fall 2002
Creating Objects in C Species Species_new(const char *name,const char *genome) { Species result = malloc(sizeof(*result)); result->name = name; result->genome = genome; return result; } CS 201J Fall 2002
Memory Leaks for (i = 0; i < 10; i++) { int *p = malloc(sizeof(*p)); *p = i*i; printf(“%d squared is %d\n”,i,*p); } 0 p i 0 CS 201J Fall 2002
Memory Leaks for (i = 0; i < 10; i++) { int *p = malloc(sizeof(*p)); *p = i*i; printf(“%d squared is %d\n”,i,*p); } 0 p 1 i 1 CS 201J Fall 2002
Memory Leaks for (i = 0; i < 10; i++) { int *p = malloc(sizeof(*p)); *p = i*i; printf(“%d squared is %d\n”,i,*p); } 0 p 1 i 3 4 9 CS 201J Fall 2002
Detecting Memory Leaks for (i = 0; i < 10; i++) { int *p = malloc(sizeof(*p)); *p = i*i; printf(“%d squared is %d\n”,i,*p); } > splint leak.c Splint 3.0.1.6 leak.c:11:6 Fresh storage p not released before scope exit A memory leak has been detected. Storage allocated locally is not released before the last reference to it is lost. CS 201J Fall 2002
free • Java’s garbage collector automatically reclaims memory • C has no garbage collector • We must release memory explicitly using the free function CS 201J Fall 2002
Releasing Memory for (i = 0; i < 10; i++) { int *p = malloc(sizeof(*p)); *p = i*i; printf(“%d squared is %d\n”,i,*p); free(p); } p i 9 81 CS 201J Fall 2002
Releasing Memory Too Soon int f() { int *i = malloc(sizeof(*i)); *i = 42; free(i); printf(“i is %d\n”,*i); } The result is undefined! CS 201J Fall 2002
Avoiding Memory Leaks • Whenever we allocate memory, there is a responsibility to release it • We can specify what part of the code has this responsibility by using annotations. • Code that uses an /*@only@*/ pointer must free the storage, or pass the responsibility somewhere else • If an /*@only@*/ pointer is lost of goes out of scope, Splint warns of a possible memory leak. CS 201J Fall 2002
Why does Splint detect the error? for (i = 0; i < 10; i++) { int *p = malloc(sizeof(*p)); *p = i*i; printf(“%d squared is %d\n”,i,*p); } > splint leak.c Splint 3.0.1.6 leak.c:11:6 Fresh storage p not released before scope exit A memory leak has been detected. Storage allocated locally is not released before the last reference to it is lost. CS 201J Fall 2002
Annotating Functions • We can annotate functions to indicate how they delegate the responsibility to release memory: /*@only@*/ /*@null@*/ void * malloc(size_t bytes); void free(void * ptr); • With these annotations, Splint knows: • Any call to malloc might return NULL • The caller of malloc is responsible for releasing the allocated memory. CS 201J Fall 2002
Annotating Functions • We can annotate functions to indicate how they delegate the responsibility to release memory: /*@only@*/ /*@null@*/ void * malloc(size_t bytes); void free(/*@only@*/ void * ptr); • With these annotations, Splint knows: • Any call to malloc might return NULL • The caller of malloc is responsible for releasing the allocated memory. • free will take responsibility for releasing an /*@only@*/ pointer. CS 201J Fall 2002
Annotating Constructors Species Species_new(const char *name, const char *genome) { Species s = malloc(sizeof(*s)); s->name = name; s->genome = genome; return s; } CS 201J Fall 2002
Annotating Constructors /*@only@*/ Species Species_new(const char *name, const char *genome) { Species s = malloc(sizeof(*s)); s->name = name; s->genome = genome; return s; } CS 201J Fall 2002
Annotating Constructors /*@only@*/ Species Species_new(const char *name, const char *genome) { Species s = malloc(sizeof(*s)); if (s == NULL) { fprintf(stderr,”Out of memory in Species_new.\n”); exit(EXIT_FAILURE); } s->name = name; s->genome = genome; return s; } CS 201J Fall 2002
Annotating Constructors /*@only@*/ Species Species_new(/*@only@*/ const char *name, /*@only@*/ const char *genome) { Species s = malloc(sizeof(*s)); if (s == NULL) { fprintf(stderr,”Out of memory in Species_new.\n”); exit(EXIT_FAILURE); } s->name = name; s->genome = genome; return s; } CS 201J Fall 2002
Dependent and Owned • Sometimes we need to have more than one pointer to the same object • However, we want to be able to check that the object is released • Why can’t we use /*@only@*/ in this situation? • /*@owned@*/ references indicate an obligation to release the memory before the reference is lost • /*@dependent@*/ references refer to objects that are /*@owned@*/ by some other pointer CS 201J Fall 2002
Use of Dependent • SpeciesSet holds references to Species objects • We might want to put a single Species object into more than one SpeciesSet • Therefore, SpeciesSet cannot take responsibility for releasing the Species object • Some other /*@owned@*/ reference must take responsibility for releasing the Species object void SpeciesSet_insert(SpeciesSet set, /*@dependent@*/ Species species); CS 201J Fall 2002
PS6: Phylogeny Revisited • We have rewritten the Phylogeny program from Problem Set 4 in C • The C version of the program has several errors: • Null pointer dereferences • Memory leaks • Abstraction violations • Your job is to use Splint annotations to find and fix them CS 201J Fall 2002
Charge • The C compiler does not check for null pointer dereferences or memory leaks • Splint can catch many of these errors if the program is annotated correctly • PS5: Due Today • PS6: Use C and Splint (Phylogeny Revisited) CS 201J Fall 2002