Top Banner
1 Lecture 5 - Memory Layout and Allocation
41

1 Lecture 5 - Memory Layout and Allocation 2 Rationale You have learnt how to grab memory using malloc() and free(). why we need to study different.

Dec 19, 2015

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

1

Lecture 5 - Memory Layout and Allocation

Page 2: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

2

Rationale

You have learnt how to grab memory using malloc() and free(). why we need to study different memory management?

We use malloc(10) to grab 10 bytes, what happens if we use memory more than 10 bytes? Will we overwrite the memory?

How to know that the memory is 10 bytes, where we can store the information?

Page 3: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

3

Topics

Heap Allocation – tweak and buddy systems Memory Bug

Review of Pointers in C

Making and Using Bad References

Overwriting Memory

Twice free

Memory Leaks

Exterminating Memory Bugs

Garbage Collection

Page 4: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

4

Details on Simple Algorithm

Block Sizes Finding Free Blocks Splitting a Free Block Finding a Suitable Block Coalescing Free Blocks (means merge) Searching for Free Blocks (three methods,

best, first and worst fits)

Page 5: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

5

Block sizes – the size to hold the data for users’ usage

The standard method for determining the size of a block, given a pointer to the block, is to store its size in the word before the pointer.

Here, the memory block that can be used is 16 bytes, the block size is 20 bytes including 4 bytes for the size

Only 16

bytes

Page 6: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

6

Determine the size Note that it uses [-1] to

point to location before the pointer (location that contains block size)

As the size is a multiple of 4, it clears the lowest two bits (3 =0000 0000 0000 0011 (hex), ~3 = 1111 1111 1111 1100

Free means the block can be used by user (binary 1)

size = ((int *) ptr)[-1]; // read integer before the memory block

correct_size = size & ~3; // clear the lower 2 bits

free = size & 1; // get low-order bit

Page 7: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

7

How to determine whether the block is free or allocated

Assume that the block size is a multiple of 4, the lowest two bits are zero.

We can use the lowest bit (least significant) to indicate whether the block is free (binary 1) or allocated (binary 0)

Page 8: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

8

How to find the free blocks If we keep a size word for

both free blocks and allocated blocks, we can skip from block to block by adding the size to the current block address to get the next block address.

Assume the pointer is pointing to the first block (allocated 12), we can then determine the address of next block (20 free)

Address ptr += 12;

Page 9: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

9

Small program pointer first points to

heap_begin (note that heap_begin[200] =“…”; the address is heap_begin

Get the size by masking the lowest two bits (note *(int *))

The next address is then obtained by ptr = ptr + size; (or ptr += size)

char *ptr = heap_begin; // get pointer to first block

while (ptr < heap_end) {

size = *((int *) ptr);

size &= ~3; // mask off low order bits

ptr += size; // increment pointer to next block

}

Page 10: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

10

Splitting a Free Block The heap is normally initialized to

look like one giant free block. (40 bytes)

When allocations occur, it would be wasteful to return a large block of free memory when a small one would do just as well. (I need 8 bytes, no point to return 40 bytes)

Therefore, the memory allocator will typically split a block if the block size is larger than the requested size. (12 allocated and 28 free)

Page 11: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

11

Finding a suitable block There are at least three methods Best fit, search all the blocks and find one that is

free and the size perfectly matches the requirements (I need 20, it returns 20.)

First fit, search all the blocks and return the first one that is free and fulfill the requirements (I need 20, the first one is 30.)

Worst fit, find the largest one that is free and splits it. (The largest is 80, I need 20. It splits this into 20 and 60. I take 20 and leaves 60 in the heap)

Page 12: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

12

Coalescing Free Blocks

Coalescing means to merge all free blocks together

In this example, two free blocks of 16 and 8 are merged together to form a larger free block of 24.

This will reduce fragmentation.

Page 13: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

13

Searching for Free Blocks Use free link list to find

free blocks In this diagram, there

are a linked list to point to the next and previous.

The advantage is that it will speed up the operation of finding a free block.

Page 14: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

14

Ways to speed up operation

To speed up the operation, we can form a free list (group free blocks together with a linked list) such as the size of 8, 16, 32, 64…)

If we want a block of 20, it can simply return a block of 32. (note that 12 are wasted.)

If we want a block of 28, it can also simply return a block of 32. In this case, 2 are wasted.

Page 15: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

15

Memory Bugs

Review of Pointers in C Making and Using Bad References Overwriting Memory Twice free Memory Leaks Exterminating Memory Bugs Garbage Collection

Page 16: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

16

Review of Pointers in C

Here, var occupies 4 bytes, *var_pt also occupies 4 bytes

*var_ptr will be allocated with 3 bytes

// take the address of a variable

int var; // declare the variable

int *var_ptr; // declare the pointer

var_ptr = &var; // take the address of var

*var_ptr = 3; // stores 3 into var

// access variable pointed to by var_ptr

if (var == *var_ptr) printf("ok\n");

Page 17: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

17

Pointers and integers can be added

Pointer can be added For an integer pointer, adding one means 4 bytes For a char pointer, adding one means one byte

For a double pointer, adding one means 8 bytes

For a structure pointer, adding one means the size of this structure

Page 18: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

18

Making and Using Bad References

The pointer is not pointing to the right location or is not properly initalised.

It might cause the program to crash.

Here, *p is not pointing to int a[].

To solve it, P = a;

int sum(int a[], int n)

{

int *p;

int sum = 0;

for (int i = 0; i < n; i++)

sum += *p++;

}

Page 19: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

19

Common bug in scanf

Note that you should supply the address rather than the variable

Use &i; instead of i It is important in

your exam.

int i;

double d;

scanf("%d %g", i, d); // wrong!!!

// here is the correct call:

scanf("%d %g", &i, &d);

Page 20: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

20

Overwriting Memory

Here, i will be incremented from 0 to array_size, not array_size – 1;

The solution is ; i < array_size;

not ; i <= array_size;

#define array_size 100

int *a = (int *) malloc(sizeof(int *) * array_size);

for (int i = 0; i <= array_size; i++)

a[i] = NULL;

Page 21: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

21

Memory bug

Here, the memory allocated is 100 bytes, not 400 bytes and a[] is defined as array pointer

The solution is:

int *a = (int *) malloc( array_size* sizeof(int));

#define array_size 100

int *a = (int *) malloc(array_size);

a[99] = 0; // this overwrites memory beyond the block

Page 22: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

22

String must be terminated by 0x00

String must be terminated by 0x00; The solution is:

char *new_s = (char *) malloc(len + 1);

char *heapify_string(char *s)

{ int len = strlen(s);

char *new_s = (char *) malloc(len);

strcpy(new_s, s);

return new_s;

}

By 0x00

Page 23: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

23

Operator precedence

Note that *a–- will decrement the pointer not the value.

We should use *(a)-- to refer to the decrement of value

// decrement a if a is greater than zero:

void dec_positive(int *a)

{

*a--; // decrement the integer

if (*a < 0) *a = 0; // make sure a is positive

}

Page 24: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

24

Memory bug Although the function

returns a pointer to a zero-valued integer, the integer is in an activation record that is deleted as soon as the function returns

Here, it might return any value once the activation is removed.

int *ptr_to_zero()

{

int i = 0;

return &i;

}

Page 25: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

25

Twice free

It means the memory pointer was freed twice.

Here, it free the memory in the routine my_write(), but it is freed in the main

void my_write(x)

{ ... use x ...

free(x); }

int *x = (int *) malloc(sizeof(int*) * N); ...

my_read(x); ...

my_write(x);

free(x); //oops, x is freed in my_write()!

Free the pointer twice

Page 26: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

26

Memory leaks

The memory that is on longer used is not returned to the memory pool.

The result is that the system will run out of memory.

The failure to deallocate (free) a block of memory when it is no longer needed is often called a memory leak

Do not return the memory block to

the pool

Page 27: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

27

Example

If it is true in the (full_msg), it will not execute to free(full_msg)

It causes memory leak

void my_function(char *msg)

{

// allocate space for a string

char *full_msg = (char *) malloc(strlen(msg) + 100);

strcpy(full_msg, "The following error was encountered: ");

strcat(full_msg, msg);

if (!display(full_msg)) return;

free(full_msg);

}

Page 28: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

28

Exterminating Memory Bugs (1)

The file name and line number where the allocation occurred. At the end of execution, any unallocated blocks that might indicate memory leaks can be listed along with the point in the code where the call to malloc() was made.

The status: whether the block is allocated or free. If a block is freed twice, this can usually be detected. The program is stopped immediately, and the debugger is invoked to show from where the extra free() was called.

Page 29: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

29

Exterminating Memory Bugs (2)

Padding before and after the block. This padding is filled with a known value such as "0xdeadbeef" so that if memory is overwritten near the boundaries of the block, the changes to the known values can easily be detected.

Links to other blocks. These enable allocated blocks to be scanned and checked.

Page 30: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

30

Exterminating Memory Bugs (3)

An allocation sequence number. This helps to identify blocks. Sometimes, you can set a breakpoint to stop when malloc() is about to allocate the block with a given sequence number. This is very useful when you want to figure out where a particular block came from.

Page 31: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

31

Garbage Collection One reason there are memory allocation

errors is that memory allocation requires the programmer to obey certain rules:

Allocate memory before using it, free memory eventually but only once, and do not read or write except to allocated memory.

Most of these rules can be automated, eliminating most memory allocation errors. Languages like Lisp, Java, and ML do not require the programmer to free memory, but not C++

Page 32: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

32

Example – return of buffer #include <stdio.h> #include <stdlib.h>

void alloc(char* buffer) { printf("Before %p\n",buffer); buffer = (char*)malloc(1000); printf("Allocated :%p\n",buffer); }

int main(void) { char* buffer; printf("Before :%p\n",buffer);

alloc(buffer); printf("After allocation :%p\n",buffer);

return 0; }

Why after allocation, buffer remains cccccccc it means that it is not yet initlised.

It is because, alloc() did not return the buffer.

Page 33: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

33

Example – change of return

Page 34: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

34

Summary

Free memory when it is not used so that it can be returned to the pool.

Free memory twice will cause error Common bug in scanf, must pass address, not

variable, int a; scanf(&a), not scanf(a)

Reserve one more byte for 0x00

Page 35: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

35

More samples - Consider the following C program: #include <string.h>#include <stdio.h> #include <stdlib.h> char* str_upper(char* str) {

char* s = (char*) malloc(str); for (int i = 0; i <= strlen(str); i++) { s[i] = toupper(*str + i);} return s; }

int main(void) { char *str[8] = {"one", "two", "three", "four", "five", "six",

"seven", "eight"}; char* s = NULL; for (int i = 0; i < 8; i++) { s = str_upper(str[i]); printf("%s\n", s); }

free(s); }

Page 36: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

36

solution1. malloc size error - The call to malloc in function str_upper allocates an incorrect amount of memory. It should be: malloc(sizeof(char) * (strlen(str) + 1))

2. off by one error - The for-loop in function str_upper is off by one. The condition of the loop needs to be: i < strlen(str)

3. pointer arithmetic- Incorrect pointer arithmetic is used inside the for-loop in function str_upper(). The line should read: s[i] = toupper(*(str+i)); 4. memory leak - Function main has a memory leak. It calls str_upper 8 times (which makes a call to malloc each time), but only frees once. The call to free needs to go inside the for-loop body, after the printf call.

Page 37: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

37

More sample – consider the following program

#include <string.h>#include <stdio.h>#include <stdlib.h>void output_reverse(char* s) { for (int i = 0, j = strlen(s); i <= strlen(s); i++, j--) { s[i] = s[j]; } printf("%s\n", s); free(s);} int main(void) { printf("Enter a 100 (or less) character string: \n"); char* str = (char*) malloc(sizeof(char) * 100); scanf("%s", str); output_reverse(str); free(str); return 0;}

Page 38: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

38

Solution

1. overwrite memory - The for-loop in output_reverse overwrites memory due to an off by one error in the condition of the loop

2. malloc size error - Function main incorrectly uses malloc. Line should be:

str = (char*) malloc(sizeof(char) * 101); The null terminator must be accounted for.

3. twice free - There are 2 calls to free for one malloc.

Page 39: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

39

Sample of program – find out the errors

#include <string.h> #include <stdio.h> #include <stdlib.h> char* copy_reverse(char* str) {

char* s = (char*) malloc(sizeof(str)); for (int i = 0, j = strlen(str); i <= strlen(str); i++, j--) s[i] = str[j]; return &s;

} int main(void) {

char* original = "original string"; char* newstring = NULL; newstring = copy_reverse(&original); fprintf("%s\n", newstring); free(original); free(newstring);

}

Page 40: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

40

The solution#include <string.h> #include <stdio.h> #include <stdlib.h> char* copy_reverse(char* str) {

char* s = (char*) malloc(sizeof(char) * (strlen(str) + 1)); for (int i = 0, j = strlen(str); i < strlen(str); i++, j--) s[i] = str[j]; return s;

} int main(void) {

char* original = "original string"; char* newstring = NULL; newstring = copy_reverse(original); fprintf("%s\n", newstring);

// free(original); free(newstring);

}

Page 41: 1 Lecture 5 - Memory Layout and Allocation 2 Rationale  You have learnt how to grab memory using malloc() and free(). why we need to study different.

41

The explanation

1. malloc size error - The call to malloc in function copy_reverse allocates an incorrect amount of memory. It should be: malloc(sizeof(char) * (strlen(str) + 1))

2. off by one error - The for-loop in function copy_reverse will overwrite memory. The condition of the loop needs to be: i < strlen(str)

3. return error - The return call in function copy_reverse returns the address of a local variable. It should return the value of of the pointer. The line should read: return s;

4. passing &char* - Function main makes a call to function copy_reverse, but passes the address of a pointer to type char, instead of a

pointer to type char.

5. free error - There is a call to free made on a non-heap variable in function main. The free(original) needs removed.