chapter 0.2 – pointers and memory. type specifiers const may be initialised but not used in any...

27
CSCI 3431: OPERATING SYSTEMS Chapter 0.2 – Pointers and Memory

Upload: rolf-carpenter

Post on 13-Jan-2016

223 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

CSCI 3431: OPERATING SYSTEMS

Chapter 0.2 – Pointers and Memory

Page 2: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Type Specifiers const

may be initialised but not used in any subsequent assignment common and useful

volatile lookup the value of the variable on every single access, do not cache,

store in a register, or use in optimisation used for memory mapping implementation dependent; no required semantics sometimes broken

restrict Applied to a pointer indicates that the pointer is the only way to access the contents of the

address improves optimization by preventing pointer aliasing

atomic It's new and I don't really know what it does ... Research suggests it can

be used to somewhat cause a type or function to be atomic with respect to pre-emption

Page 3: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Strings

In C, a string is nothing more than an array of characters.

There is no field to store the length or any other data about the string.

To mark the end of the string, a NULL value (i.e., all bits zero) is used.

String library functions expect there to be a terminating NULL character.

Because a string is an array, I'm going to ignore them when talking about memory and only discuss arrays.

Page 4: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Memory Management

C is nothing but glorified assembly language To program in C effectively, one needs an

understanding of:a. the memory modelb. calling conventions

Three basic ideas:1. Static memory – things that don't change2. Stack memory – things associated with function

calls3. Heap memory – globals, runtime allocation, etc.

Page 5: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Basic Memory Model

Page 6: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

The StackEvery function call creates a stack framethat contains:

1. Arguments (values for parameters)2. Return address3. Context (saved register values)4. Local variables

Val/Address Arg 2: EBP + 12

Val/Address Arg 1: EBP + 8

Return Address

Old/Saved EBP

Local Variable 1: EBP - 4

Local Variable 2: EBP - 8

EAX (saved)

EDX (saved)

Empty Space

Page 7: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Stack Storage

The stack stores words (i.e., 64 bit values that can fit in a register )

Anything that can't fit on the stack is generally stored in the heap and it's address put on the stack

Thus, we have to know where something is located to know if we have a value or an address

Page 8: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Storage Classes We can somewhat control where things are stored

using storage classes auto: give the variable automatic storage on the

stack; can only be used in functions register: try to keep the variable in a register; may

by ignored; & cannot be used on register variables static

inside functions, the variable retains it value between function calls (heap variable, not stack)

outside functions, it indicates a variable declaration cannot be linked to other compilation units (files)

extern : declare the variable; storage will be defined elsewhere and location determined at link time

Page 9: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Calling Conventions

We put arguments (values for function parameters) on the stack when we call a function.

Call by Value: We are putting a value (e.g., int, float, char) on the stack.

Call by Reference: We are putting the address of the value(s) on the stack. The value is somewhere else (possibly the heap).

Page 10: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Arrays

Arrays are kept in heap storage. The stack only ever stores the

address. A pointer is a variable that stores an

address. To manipulate arrays, we can offset

from the base address using [] notation to obtain a value.

We can also use the pointer directly and we can make pointers for non-arrays if desired.

Page 11: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Syntax

Variables can be declared as pointer by prefixing them with *.int *x;

Pointers can be dereferenced – that is, the value from the stored address is obtained. int z = *x;

The address of something can be obtained by prefixing it with &.x = &argc;

NOTE: It is bad if you take the address of something on the stack that can go away!

Page 12: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Pointers

int x = 5;

int *p;

p = &x;

printf ("%d %d", x, *p);

* := LHS, "is a pointer" := RHS, "take value of" & := "take address of"

Page 13: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Example

int x = 1, y = 2, z[10];

int *ip; /* ip is pointer to integer */

ip = &x; /* ip points to x */

y = *ip; /* y is now 1, the value in x */

*ip = 0; /* x is now 0 */

ip = &z[0]; /* ip points to z[0] */

*ip = y; /* z[0] now 1, the value in y */

Page 14: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Why we need pointers ...

void swap (int x, int y) { int tmp = x; x = y; y = tmp;}

x and y are on the stack and use call by value

This function swaps the values of two stack variables that go away when the function returns causing x, y to be deleted.

Page 15: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Using Pointers

void swap (int *px, int *py) { int tmp = *px; *px = *py; *py = tmp;}

int x = 1, y = 2; swap (&x, &y);

Page 16: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Function Pointers

There are no objects and methods However, we can pass a function

around without using an object We simply pass the address of the

function (since it's in memory as well)

Function names, like array names, are actually addresses

When using a function pointer we need to dereference the address to action the code

Page 17: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Example: Function Pointer

#include <stdio.h>void fun (int a) { printf("Value of a is %d\n", a);} int main () {

/* Define and initialise a function pointer */ void (*fun_ptr)(int) = &fun;

/* Invoke fun() using fun_ptr */ (*fun_ptr)(10); return 0;}

Page 18: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Function Pointersvoid bsearch (

const void *key,const void *base,size_t n, size_t size,int (*cmp)(const void *keyval, const void *datum)

);

char data[256][64];

bsearch("tami",data,64*sizeof(char),256,strcmp);

Notes: void* is typically used to mean "pointer to anything"size_t is the type of the integers that are returned by sizeof

Page 19: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Dynamic Memory Management

We can put things on the heap at runtime

For example we can request heap space into which we can read a file's contents

We use malloc() to do memory allocation

When the memory is no longer needed, we can use free() to release it for re-use

Java provides a "garbage" collector to manage the heap for us ... in C we do it ourselves.

Page 20: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Example: Dynamic Memory

/* Allocate a pair of buffers */char *buf1 = malloc(256 * sizeof (char));char *buf2 = calloc(256, sizeof(char));

/* resize buf1 and “leak” buf2 */buf2 = realloc(buf1, 128 * sizeof (char));

/* Cause a runtime error with a double free */ free(buf1), free(buf2);

Page 21: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Definitions and Declarations Declarations say something exists.

They provide enough information so that the file can be compiled.

Where the declared entity will be located is determined during linking.

The mechanism is in place to support the individual compilation of files and is the basis of "header files" (which mostly store declarations)

Definitions assign memory to something.

Page 22: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Complex Declarations char **argv

pointer to pointer to char int (*daytab)[13]

pointer to array[13] of int int *daytab[13]

array[13] of pointer to int void *comp()

function return pointer to void void (*comp)()

pointer to function returning void

Page 23: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Insane Declarations

char (*(*x())[])() function returning pointer to array[] of

pointers to functions returning char char(*(*x[3])())[5]

array[3] of pointers to functions returning pointer to array[5] of chars

Page 24: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Structures: Records for Data/* Method A: Not using typedef */struct point { int x; int y;};struct point origin = { 0, 0 };

/* Method B: Compressed version of method A */struct point { int x; int y;} origin = { 0, 0 };

/* Method C: Using typedef */typedef struct { int x; int y;} point_t;point_t origin = { 0, 0 };

Page 25: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Recursive Structures

typedef struct node { char *data; struct node next;} node_t;

node_t *list = malloc(sizeof(node_t));list->data = “Meredith”;list->next = NULL;

node_t *list2 = malloc(sizeof(node_t));list2->data = “Tami”;list2->next = list;

Page 26: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Unions

Unions are used to save memory The size of a union is equal to the size of the

largest field It is up to the programmer to use the fields

correctly

union number {

int ival;

float fval;

} n;

n.ival = 1;

printf(“%f\n”, n.fval); /* works, but not a cast */

Page 27: Chapter 0.2 – Pointers and Memory. Type Specifiers  const  may be initialised but not used in any subsequent assignment  common and useful  volatile

Do you

?