Dynamic Memory Allocation Memory Allocation: malloc() Using ...

124 downloads 136 Views 39KB Size Report
Pointers are used to keep track of dynamic memory. Memory Allocation: malloc(). ○ Additional memory to create dynamic data ... The anatomy of a malloc() call.
57:017 Computers in Engineering—C Dynamic Memory Allocation

Dynamic Memory Allocation z

We often don’t know at compile time how much data space a program will need: e.g. may not know how large an array will be needed to hold input data

z

z

Solution 1: Use arrays of maximum possible size that we would encounter Very wasteful, wasteful as we require lots and lots of memory that we may never use Total amount of memory required by the program may exceed acceptable limit

z z

z

Solution 2: Dynamic memory We can create arrays ( or other data structures) “on the fly”, asking for memory as we need it and releasing it for possible reuse when finished Pointers are used to keep track of dynamic memory

z

z

Memory Allocation: malloc()

Using malloc() z

z

z

z z

Additional memory to create dynamic data structures must be requested from the system. The function malloc() () allocates a requested number of bytes from the system to the program Returns a generic pointer to the allocated memory The program can cast this pointer to any desired data type

sizeof() operator z z

z

Determines the size in bytes of a data type When an array name is specified as the argument, returns the number of bytes in the array Typically: z z z z

z

sizeof(int) = 4 sizeof(float) = 4 sizeof(char) = 1 sizeof(double) = 8

Later, we will use sizeof() to determine the size of more complex data types-e.g. structures

Must request a specific number of bytes from malloc() z

z

Use sizeof operator to get bytes required by data type

Must cast returned pointer to correct type #include int *xPtr; /* Allocate space for 100 int values */ xPtr = (int *) malloc(100*sizeof(int)); *xPtr = 3; /* Sets first int to 3 */ xPtr[99] = 2; /* Sets 100th int to 2 */ *(xPtr + 99) = 2; /* Same thing as above */

The anatomy of a malloc() call pointer to desired type

total number of bytes to be allocated

xPtr = ( (int *) ) malloc( ( 100*sizeof(int) ( ) ) ); cast the pointer returned by malloc() to the desired pointer type

number of elements to be allocated

number of bytes per element

1

The anatomy of a malloc() call

Additonal malloc() details Returns NULL if memory could not be allocated

z

xPtr = (int *) malloc( 100*sizeof(int) ); xPtr[1] = 10;

double *dPtr; dPtr = (double *) malloc(100*sizeof(double)); if (dPtr == NULL) { printf("Could not allocate memory\n"); …

What is going on in the computer memory? xPtr ÅÆ

Address

Value

6000

8000

…..

…..

8000

unknown

*(xPtr+1), xPtr[1] ÅÆ

8004

10

…..

Should always use sizeof() to get the size of a data type

z

*xPtr, xPtr[0] ÅÆ

z

Systems vary in data type and structure space usage, even in standard data types like int

…..

*(xPtr+98), xPtr[98] ÅÆ

8392

unknown

*(xPtr+99), xPtr[99] ÅÆ

8396

unknown

&(xPtr[98]) is memory address of xPtr[98] and is equal to 8392

Another memory allocation function: calloc() number of elements

size of an element

Deallocating Memory with free() z

xPtr = (int *) calloc( 100, sizeof(int) ); z z

Note: two parameters Main difference between malloc() and calloc() is that calloc() initializes the allocated memory to all zeros.

z

When a dynamically allocated data structure is no longer needed, it can be given back to the system for reallocation, using the free() function int *xPtr; xPtr = (int *)) malloc(100 malloc(100*sizeof(int)); sizeof(int)); .... free(xPtr); After free(), the values pointed to by xPtr are no longer valid Using xPtr without reinitializing may result in strange problems

z

Returning a Dynamically Allocated Array Assume that you want to write a subroutine to allocate an array and return the array. There are two ways to return the array:

z

z 1 1.

2.

z

Use a return statement to return the address of the array. Return the address of the array by reference.

You need to decide which of the two methods you are going to use before you can write you subroutine.

Example: Returning a Dynamically Allocated Array Problem Statement: Write a subroutine that allocates an N element 1D array of integers, initializes the array from 0 to N-1, and returns the array. y Start this problem by listing the inputs and outputs of the subroutine

z

z z z

Inputs: int size = number of elements of array Outputs: int * array = a 1D array of ints initialized from 0 to N-1.

2

Example: Returning a Dynamically Allocated Array Decide how the input and output variables will be passed to and from the subroutine.

z z z

Example: Case 1, Return array using return statement int * InitArray(int size){ int * array; int i;

Input variables can be passed by value or by reference Output variable can be returned using a return statement or by reference.

array = (int *) malloc(size*sizeof(int)); if (array == NULL){ printf(“Error: Unable to allocate array\n”); exit(-1); }

Input variable “size” does not need to be changed so pass by value Output variable “array” can be returned using a return statement or by reference.

z z z z

for(i=0;i