Pointers and Memory - Swarthmore Collegebryce/cs31/f16/slides/w05b_memory.pdf · Memory Leak •...
Transcript of Pointers and Memory - Swarthmore Collegebryce/cs31/f16/slides/w05b_memory.pdf · Memory Leak •...
PointersandMemory9/29/16
Recall:Allocating(Heap)Memory
• ThestandardClibrary(#include<stdlib.h>)includesfunctionsforallocatingmemory
void *malloc(size_t size)• Allocatesize bytesontheheapandreturnapointertothebeginningofthememoryblock
void free(void *ptr)• Releasethemalloc()ed blockofmemorystartingatptr backtothesystem
Whatdoyouexpecttohappentothe100-bytechunkifwedothis?//Whathappenstothese100bytes?
int *ptr = malloc(100);
ptr = malloc(2000);
A. The100-bytechunkwillbelost.
B. The100-bytechunkwillbeautomaticallyfreed(garbagecollected)bytheOS.
C. The100-bytechunkwillbeautomaticallyfreed(garbagecollected)byC.
D. The100-bytechunkwillbethefirst100bytesofthe2000-bytechunk.
E. The100-bytechunkwillbeaddedtothe2000-bytechunk(2100bytestotal).
MemoryLeak
• Memorythatisallocated,andnotfreed,forwhichthereisnolongerapointer.
• Inmanylanguages(Java,Python,…),thismemorywillbecleanedupforyou.• “Garbagecollector”findsunreachablememoryblocks,freesthem.• Cdoesn’tdoesNOTdothisforyou!
Whydoesn’tCdogarbagecollection?A. It’simpossibleinC.
B. Itrequiresalotofresources.
C. Itmightnotbesafetodoso.(breakprograms)
D. Ithadn’tbeeninventedatthetimeCwasdeveloped.
E. Someotherreason.
MemoryBookkeeping• Tofreeachunk,youMUSTcallfreewiththesamepointerthatmalloc gaveyou.(oracopy)
• ThestandardClibrarykeepstrackofthechunksthathavebeenallocatedtoyourprogram.• Thisiscalled“metadata”– dataaboutyourdata.
• Wait,wheredoesitstorethatinformation?• It’snotlikeitcanusemalloc()togetmemory…
Whereshouldwestorethismetadata?A. IntheCPU
B. Inmainmemory
C. Ontheharddrive
D. Somewhereelse
MetadataHeap
int *iptr = malloc(8);
MetadataHeap
FirstByte
… … …
… … … LastByte
int *iptr = malloc(8);
MetadataHeap
Meta Data
Meta Data
FirstByte
… … …
… … … LastByte
int *iptr = malloc(8);
• CLibrary:“Letmerecordthisallocation’sinfohere.”• Sizeofallocation• Maybeotherinfo
MetadataHeap
Meta Data Meta Data
FirstByte
… … …
… … … LastByte
Meta Data Meta Data
Other
Data
int *iptr = malloc(8);
• Forallyouknow,therecouldbeanotherchunkafteryours.
MetadataHeap
Meta Data Meta Data
FirstByte
… … …
… … … LastByte
Meta Data Meta Data
Other
Data
int *iptr = malloc(8);
• Takeaway:veryimportantthatyoustaywithinthememorychunksyouallocate.
• Ifyoucorruptthemetadata,youwillgetweirdbehavior.
Valgrind isyournewbestfriend.
PointersasArrays
• “Whydidyouallocate8bytesforanint pointer?Isn’tanint only4bytes?”• int *iptr = malloc(8);
• Recall:anarrayvariableactslikeapointertoablockofmemory.Thenumberin[]isanoffsetfrombucket0,thefirstbucket.
• Wecantreatpointersinthesameway!
Heap
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
PointersasArrays
PointersasArrays
Heap
1st integer
2nd integer
3rd integer
4th integer
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
PointersasArrays
Heap
1st integer
2nd integer
3rd integer
4th integer
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
TheCcompilerknowshowbiganintegeris.
Asanalternativewayofdereferencing,youcanuse[]’slikeanarray.
TheCcompilerwilljumpaheadtherightnumberofbytes,basedonthetype.
PointersasArrays
Heap
iptr[0]
iptr[1]
iptr[2]
iptr[3]
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
PointersasArrays
Heap
iptr[0]
iptr[1]
iptr[2]
iptr[3]
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
iptr[2] = 7;
1.Startfromthebaseofiptr.
PointersasArrays
Heap
iptr[0]
iptr[1]
iptr[2]
iptr[3]
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
iptr[2] = 7;
1.Startfromthebaseofiptr.
2.Skipforwardbythesizeoftwoints.
PointersasArrays
Heap
iptr[0]
iptr[1]
7
iptr[3]
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
iptr[2] = 7;
1.Startfromthebaseofiptr.
2.Skipforwardbythesizeoftwoints.
3.Treattheresultasanint.(Accessthememorylocationlikeatypicaldereference.)
PointersasArrays
• Thisisoneofthemostcommonwaysyou’llusepointers:• Youneedtodynamicallyallocatespaceforacollectionofthings(ints,structs,whatever).• Youdon’tknowhowmanyatcompiletime.
float *student_gpas = NULL;
student_gpas = malloc(n_students * sizeof(int));
…
student_gpas[0] = …;
student_gpas[1] = …;
PointerArithmetic
• Additionandsubtractionworkonpointers.
• Cautomaticallyincrementsbythesizeofthetypethat’spointedto.
PointerArithmetic
Heap
1st integer
2nd integer
3rd integer
4th integer
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
PointerArithmetic
Heap
1st integer
2nd integer
3rd integer
4th integer
int *iptr = NULL;
iptr = malloc(4 * sizeof(int));
int *iptr2 = iptr + 3;
Skipaheadby3timesthesizeofiptr’stype(integer,size:4bytes).
Otherusesforpointers…
1. Allowingafunctiontomodifyavariable.
2. Allowingafunctiontoreturnmemory.
3. Manymore…
FunctionArguments
• Argumentsarepassedbyvalue• Thefunctiongetsaseparatecopy ofthepassedvariable
int func(int a, int b) {
a = a + 5;return a - b;
}
int main() {
int x, y; // declare two integersx = 4;
y = 7;y = func(x, y);printf(“%d, %d”, x, y);
}
Stack
main:x:
y:
func:a:
b:
4
7
4
7
4
7
FunctionArguments
• Argumentsarepassedbyvalue• Thefunctiongetsaseparatecopy ofthepassedvariable
int func(int a, int b) {
a = a + 5;return a - b;
}
int main() {
int x, y; // declare two integersx = 4;
y = 7;y = func(x, y);printf(“%d, %d”, x, y);
}
Stack
main:x:
y:
4
7
4
7
Itdoesn’tmatterwhatfuncdoeswithaandb.Thevalueofxinmaindoesn’tchange.
FunctionArguments
• Argumentscanbepointers!• Thefunctiongetstheaddressofthepassedvariable!
void func(int *a) {*a = *a + 5;
}
int main() {int x = 4;
func(&x);printf(“%d”, x);
}
Stack
main:
PointerArguments
• Argumentscanbepointers!• Thefunctiongetstheaddressofthepassedvariable!
void func(int *a) {*a = *a + 5;
}
int main() {int x = 4;
func(&x);printf(“%d”, x);
}
Stack
main:
x: 4
PointerArguments
• Argumentscanbepointers!• Thefunctiongetstheaddressofthepassedvariable!
void func(int *a) {*a = *a + 5;
}
int main() {int x = 4;
func(&x);printf(“%d”, x);
}
Stack
main:
func:a:
x: 4
PointerArguments
• Argumentscanbepointers!• Thefunctiongetstheaddressofthepassedvariable!
void func(int *a) {*a = *a + 5;
}
int main() {int x = 4;
func(&x);printf(“%d”, x);
}
Stack
main:
func:a:
x: 9
Dereferencepointer,setvaluethatapointsto.
PointerArguments
• Argumentscanbepointers!• Thefunctiongetstheaddressofthepassedvariable!
void func(int *a) {*a = *a + 5;
}
int main() {int x = 4;
func(&x);printf(“%d”, x);
}
Stack
main:
x: 9
Prints:9
Haven’tweseenthissomewherebefore?
Readfile Library
• We’veseensawthisinlab2and4withread_intandread_float.• Thisiswhyyouneededan&.• e.g.,
int value;status_code = read_int(&value);
• You’reaskingread_int tomodifyaparameter,soyougiveitapointertothatparameter.• read_int willdereferenceitandsetit.
Otherusesforpointers…
1. Allowingafunctiontomodifyavariable.
2. Allowingafunctiontoreturnmemory.
3. Manymore…
Canyoureturnanarray?
• Supposeyouwantedtowriteafunctionthatcopiesanarrayofintegers.
copy_array(int array[], int len) {int result[len];for(int i=0; i<len; i++)
result[i] = array[i];return result;
}Thisisaterribleidea.(Don’tworry,compilerwontletyoudothisanyway.)
Howmanybugscanyoufind?A=1,B=2,…
Considerthememory…
copy_array5(int array[]) {
int result[5];
for(int i=0; i<5; i++)
result[i] = array[i];
return result;
}
(In main):
copy = copy_array(…)
copy_array5:
main:
copy:
result
Considerthememory…
main:
copy:
resultresult
copy_array5(int array[]) {
int result[5];
for(int i=0; i<5; i++)
result[i] = array[i];
return result;
}
(In main):
copy = copy_array(…)
copy_array5:
Considerthememory…
copy_array5(int array[]) {
int result[5];
for(int i=0; i<5; i++)
result[i] = array[i];
return result;
}
(In main):
copy = copy_array(…)main:
copy:
Whenwereturnfromcopy_array,itsstackframeisgone!
Leftwithapointertonowhere.
UsingtheHeapint *copy_array(int array[], int len) {
int *result = malloc(len * sizeof(int));
for(int i=0; i<len; i++)
result[i] = array[i];
return result;
}
0x0
0xFFFFFFFF
Operatingsystem
Stack
TextDataHeap
result:
malloc memoryisontheheap.
Doesn’tmatterwhathappensonthestack(functioncalls,returns,etc.)
Otherusesforpointers…1. Allowingafunctiontomodifyavariable.
2. Allowingafunctiontoreturnmemory.
• Thesearebothverycommon.Youshouldbeusingtheminlab4.
3. Manymore…• Avoidingcopies(structs …comingupshortly)• Sharingbetweenthreads(endofthesemester)
PointerstoPointers• Whystopatjustonepointer?
int **double_iptr;
• “Apointertoapointertoanint.”• Dereferenceonce:pointertoanint• Dereferencetwice:int
• Commonlyusedto:• Allowafunctiontomodifyapointer(datastructures)• Dynamicallycreateanarrayofpointers.• (Programcommandlineargumentsusethis.)
int main(int argv, char** argv)
Recall:structs ontheheapstruct student {
char name[40];
int age;
double gpa;
}
struct student *bob = NULL;
bob = malloc(sizeof(struct student));
PointerstoStructs -> operator
struct student *bob = NULL;
bob = malloc(sizeof(struct student));
(*bob).age = 20;
bob->gpa = 3.5;
The-> operatorisashortcuttodoadereference(*)andafieldaccess(.).
Arraysvs.Pointers
Howarearrayvariablesdifferentfrompointervariables?Thinkofasmanydifferencesasyoucan.
• Declareddifferently.int arr[5];int *ptr;ptr = malloc(5 * sizeof(int));
• Storeddifferently• Stack• Heap
• PointersareLvalues
Lvalues
• Anythingthatcanbeontheleft-handsideofanassignment.• Examples:• int• float• Structs (e.g.struct student)• pointers
• Arraysarenotlvalues.Youcan’tmoveadifferentaddressintoanarrayvariable.
Struct Parameters:PassbyValue:void test(struct student s1){
s1.age = 20;s1.name[0] = ‘X’;
}int main() {struct student jo;strcpy(jo.name, “Jo”);jo.age = 18;test(jo);
}
test:
main:
STACK
Q1: What is the value of the argument jo?
Q2: What value does param s1 get?Q3: Draw the StackQ4: What is value of jo after the
function call?