CMPSC 311 - Introduction to Systems Programming
CMPSC 311- Introduction to Systems Programming Module: Variables - - PowerPoint PPT Presentation
CMPSC 311- Introduction to Systems Programming Module: Variables - - PowerPoint PPT Presentation
CMPSC 311- Introduction to Systems Programming Module: Variables Arrays and Pointers Professor Patrick McDaniel Fall 2016 CMPSC 311 - Introduction to Systems Programming Variable Storage Classes C (and other languages) have several
CMPSC 311 - Introduction to Systems Programming Page
Variable Storage Classes
- C (and other languages) have several storage that are
defined by their scope
- auto – these are automatically allocated and deallocated
variables (local function variables declared on stack)
- global – globally defined variables that can be accessed
anywhere within the program
- extern is used in .c/.h files to indicate a variable defined
elsewhere
- static – a variable that is global to the local file only
- Static is used identify variable as local only
static int localScopeVariable; // Static variable extern int GlobalVariable; // Global variable defined elsewhere
CMPSC 311 - Introduction to Systems Programming Page
Rules for initialization
- In general, static or global variables are giving a default
value and auto are indeterminate
- meaning that the compiler can do anything it wants, which for
most compilers is take whatever value is in memory
- You cannot depend on indeterminate values
C89 Specification : If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant. C99 Specification : If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then: — if it has pointer type, it is initialized to a null pointer; — if it has arithmetic type, it is initialized to (positive or unsigned) zero; — if it is an aggregate, every member is initialized (recursively) according to these rules; — if it is a union, the first named member is initialized (recursively) according to these rules.
CMPSC 311 - Introduction to Systems Programming Page
Arrays
- type name[size];
- example allocates 100 ints worth of memory
- initially, each array element contains garbage data
- an array does not know its own size
- sizeof(scores) is not reliable; only works in some situations
- recent versions of C allow the array size to be an expression
4
int scores[100]; int n=100; int scores[n]; // OK in C99
C Arrays are zero indexed!
CMPSC 311 - Introduction to Systems Programming Page
Initializing and using arrays
- type name[size] = {value, value, ..., value};
- allocates and array and fills it with supplied values
- if fewer values are given than the array size, fills rest with 0
- name[index] = expression;
- sets the value of an array element
5
int primes[6] = {2, 3, 5, 6, 11, 13}; primes[3] = 7; primes[100] = 0; // smash! // 1000 zeroes int allZeroes[1000] = {0};
CMPSC 311 - Introduction to Systems Programming Page
Setting array values (cont.)
6
int val[3] = { 5, 5, 5 }; printf( "val [%d, %d, %d]\n", val[0], val[1], val[2] ); int val1[3] = { 0 }; printf( "val1 [%d, %d, %d]\n", val1[0], val1[1], val1[2] ); int val2[3] = { 1 }; printf( "val2 [%d, %d, %d]\n", val2[0], val2[1], val2[2] ); int val3[3] = {}; printf( "val3 [%d, %d, %d]\n", val3[0], val3[1], val3[2] ); int val4[3] = { [0 ... 2] = 1 }; printf( "val4 [%d, %d, %d]\n", val4[0], val4[1], val4[2] ); val [5, 5, 5] val1 [0, 0, 0] val2 [1, 0, 0] val3 [0, 0, 0] val4 [1, 1, 1]
CMPSC 311 - Introduction to Systems Programming Page
Setting array values (cont.)
7
int val[3] = { 5, 5, 5 }; printf( "val [%d, %d, %d]\n", val[0], val[1], val[2] ); int val1[3] = { 0 }; printf( "val1 [%d, %d, %d]\n", val1[0], val1[1], val1[2] ); int val2[3] = { 1 }; printf( "val2 [%d, %d, %d]\n", val2[0], val2[1], val2[2] ); int val3[3] = {}; printf( "val3 [%d, %d, %d]\n", val3[0], val3[1], val3[2] ); int val4[3] = { [0 ... 2] = 1 }; printf( "val4 [%d, %d, %d]\n", val4[0], val4[1], val4[2] ); [5, 5, 5] [0, 0, 0] [1, 0, 0] [0, 0, 0] [1, 1, 1]
// Best approach to init all values int val4[3] = { [0 ... 2] = 1 };
CMPSC 311 - Introduction to Systems Programming Page
Setting array values (cont.)
8
int val[3] = { 5, 5, 5 }; printf( "val [%d, %d, %d]\n", val[0], val[1], val[2] ); int val1[3] = { 0 }; printf( "val1 [%d, %d, %d]\n", val1[0], val1[1], val1[2] ); int val2[3] = { 1 }; printf( "val2 [%d, %d, %d]\n", val2[0], val2[1], val2[2] ); int val3[3] = {}; printf( "val3 [%d, %d, %d]\n", val3[0], val3[1], val3[2] ); int val4[3] = { [0 ... 2] = 1 }; printf( "val4 [%d, %d, %d]\n", val4[0], val4[1], val4[2] ); val [5, 5, 5] val1 [0, 0, 0] val2 [1, 0, 0] val3 [0, 0, 0] val4 [1, 1, 1]
CMPSC 311 - Introduction to Systems Programming Page
Beware of the Internet ….
- There is a lot misinformation, bad code, and bad advice
- n the Internet (e.g., stackoverflow.com)
- Don’t trust everything you read …
9
int inspect_stack(void) { char values[100] = { 1 }; printf("Values[0, 1, 2] = %d %d %d\n", values[0], values[1], values[2]); return(0); } Values[0, 1, 2] = 1 0 0
CMPSC 311 - Introduction to Systems Programming Page
Multi-dimensional arrays
- type name[rows][columns] = {{values}, ..., {values}};
- allocates a 2D array and fills it with predefined values
10
// a 2 row, 3 column array of doubles double grid[2][3]; // a 3 row, 5 column array of ints int matrix[3][5] = { {0, 1, 2, 3, 4}, {0, 2, 4, 6, 8}, {1, 3, 5, 7, 9} }; grid[0][2] = (double) matrix[2][4]; // which val?
CMPSC 311 - Introduction to Systems Programming Page
Arrays as parameters
- It’s tricky to use arrays as parameters
- arrays are effectively passed by reference (not copied)
- arrays do not know their own size
11
int sumAll(int a[]); // prototype declaration int main(int argc, char **argv) { int numbers[5] = {3, 4, 1, 7, 4}; int sum = sumAll(numbers); return 0; } int sumAll(int a[]) { int i, sum = 0; for (i = 0; i < ...??? }
CMPSC 311 - Introduction to Systems Programming Page
Arrays as parameters
- Solution 1: declare the array size in the function
- problem: code isn’t very flexible
12
int sumAll(int a[5]); // prototype declaration int main(int argc, char **argv) { int numbers[5] = {3, 4, 1, 7, 4}; int sum = sumAll(numbers); return 0; } int sumAll(int a[5]) { int i, sum = 0; for (i = 0; i < 5; i++) { sum += a[i]; } return sum; }
CMPSC 311 - Introduction to Systems Programming Page
Arrays as parameters
- Solution 1: declare the array size in the function
- problem: code isn’t very flexible
13
int sumAll(int a[5]); // prototype declaration int main(int argc, char **argv) { int numbers[5] = {3, 4, 1, 7, 4}; int sum = sumAll(numbers); return 0; } int sumAll(int a[5]) { int i, sum = 0; for (i = 0; i < 5; i++) { sum += a[i]; } return sum; }
int sumAll(int a[5]) Note: the size is not enforced!
CMPSC 311 - Introduction to Systems Programming Page
Arrays as parameters
- Solution 2: pass the size as a parameter
14
int sumAll(int a[], int size); // Array passed by reference int main(int argc, char **argv) { int numbers[5] = {3, 4, 1, 7, 4}; int sum = sumAll(numbers, 5); printf("sum is: %d\n", sum); return 0; } int sumAll(int a[], int size) { int i, sum = 0; for (i = 0; i <= size; i++) { // CAN YOU SPOT THE BUG? sum += a[i]; } return sum; }
CMPSC 311 - Introduction to Systems Programming Page
Returning an array
- Local variables, including arrays, are stack allocated
- they disappear when a function returns
- therefore, local arrays can’t be safely returned from functions
15
int[] copyarray(int src[], int size) { int i, dst[size]; // OK in C99 for (i = 0; i < size; i++) { dst[i] = src[i]; } return dst; // NO -- bug }
CMPSC 311 - Introduction to Systems Programming Page
Solution: an output parameter
- Create the “returned” array in the caller
- pass it as an output parameter to copyarray
- works because arrays are effectively passed by reference
16
void copyarray(int src[], int dst[], int size) { int i; for (i = 0; i < size; i++) { dst[i] = src[i]; } }
CMPSC 311 - Introduction to Systems Programming Page
OS and processes (redux)
- The OS lets you run multiple applications at once
- an application runs within an OS “process”
- the OS timeslices each CPU between runnable processes
- happens very fast; ~100 times per second!
17
- • •
process N process 1 process 2
- perating system
CMPSC 311 - Introduction to Systems Programming Page
Processes and virtual memory
- OS gives each process the illusion of its own, private
memory
- called the process’ address space
- contains the process’ virtual
memory, visible only to it
- 32-bit pointers on 32- bit machine
- 64-bit pointers on 64- bit machine
18
0x00000000 0xFFFFFFFF process’ address space
contains code, data, libraries, stack, etc.
CMPSC 311 - Introduction to Systems Programming Page
Loading
- When the OS loads a
program, it:
- creates an address space
- inspects the executable file
to see what’s in it
- (lazily) copies regions of the
file into the right place in the address space
- does any final linking,
relocation, or other needed preparation
19
0x00000000 0xFFFFFFFF
OS kernel [protected] stack shared libraries heap (malloc/free) read/write segment .data, .bss read-only segment .text, .rodata
CMPSC 311 - Introduction to Systems Programming Page
Loading (regions)
20
0x00000000 0xFFFFFFFF
OS kernel [protected] stack shared libraries heap (malloc/free) read/write segment .data, .bss read-only segment .text, .rodata
Code Static Data Dynamic Data Code/Data for Libraries Process State/local variables
CMPSC 311 - Introduction to Systems Programming Page
The stack in detail …
- Used to store data associated
with function calls
- when you call a function, compiler-
inserted code will allocate a stack frame to store:
- the function call arguments
- the address to return to
- local variables used by the function
- a few other pieces of bookkeeping
21
- ffset
contents 4 8 12 16 20 24 a stack frame
int f(int p1, int p2) { int x; int a[3]; ... return x; }
x a[0] a[1] a[2] return address p1 p2
CMPSC 311 - Introduction to Systems Programming Page
Stack example
22
#include <stdio.h> #include <stdint.h> int showstack( int i, int j ) { int k = 2; int32_t l[2]; printf( "i is at [%p], size [%lu], value [%d]\n", &i, sizeof(i), i ); printf( "j is at [%p], size [%lu], value [%d]\n", &j, sizeof(j), j ); printf( "k is at [%p], size [%lu], value [%d]\n", &k, sizeof(k), k ); printf( "l is at [%p], size [%lu], value [%d]\n", &l[1], sizeof(l[1]), l[1] ); return( 0 ); } int main( void ) { printf( "Hello world!\n" ); showstack( 3, 4 ); return( 0 ); }
CMPSC 311 - Introduction to Systems Programming Page
Stack example
23
mcdaniel@ubuntu:~/tmp/helloworld$ make gcc showstack.c -o showstack mcdaniel@ubuntu:~/tmp/helloworld$ ./showstack Hello world! i is at [0x7fffe345f0ec], size [4], value [3] j is at [0x7fffe345f0e8], size [4], value [4] k is at [0x7fffe345f0fc], size [4], value [2] l is at [0x7fffe345f104], size [4], value [0] mcdaniel@ubuntu:~/tmp/helloworld$ ... int showstack( int i, int j ) { int k = 2; int32_t l[2]; ... int main( void ) { printf( "Hello world!\n" ); showstack( 3, 4 ); return( 0 ); }
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
24
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
25
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
26
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
27
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
28
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
29
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
30
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a g param
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
31
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a g param
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
32
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a g param
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
33
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
34
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 f p1, p2, x, a
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
35
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
36
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 g param
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
37
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1 g param
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
38
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g) main
argc, argv, n1
CMPSC 311 - Introduction to Systems Programming Page
The stack in action
39
int main(int argc, char **argv) { int n1 = f(3, -5); n1 = g(n1); } int f(int p1, int p2) { int x; int a[3]; ... x = g(a[2]); return x; } int g(int param) { return param * 2; }
OS kernel [protected] stack heap (malloc/free) read/write segment globals read-only segment (main, f, g)
CMPSC 311 - Introduction to Systems Programming Page
Addresses and &
- &foo produces the virtual address of foo
40
#include <stdio.h> int foo(int x) { return x+1; } int main(int argc, char **argv) { int x, y; int a[2]; printf("x is at %p\n", &x); printf("y is at %p\n", &y); printf("a[0] is at %p\n", &a[0]); printf("a[1] is at %p\n", &a[1]); printf("foo is at %p\n", &foo); printf("main is at %p\n", &main); return 0; }
CMPSC 311 - Introduction to Systems Programming Page
Pointers
- type *name; // declare a pointer
- type *name = address; // declare + initialize a pointer
- a pointer is a variable that contains a memory address
- it points to somewhere in the process’ virtual address space
41
int main(int argc, char **argv) { int x = 42; int *p; // p is a pointer to an integer p = &x; // p now stores the address of x printf("x is %d\n", x); printf("&x is %p\n", &x); printf("p is %p\n", p); return 0; }
CMPSC 311 - Introduction to Systems Programming Page
A stylistic choice
- C gives you flexibility in how you declare pointers
- one way can lead to visual trouble when declaring multiple
pointers on a single line
- the other way is what I prefer
42
int* p1; int *p2; // I prefer int* p1, p2; // bug?; equivalent to int *p1; int p2; int* p1, * p2; // correct
- r
int *p1, *p2; // correct, preferred
CMPSC 311 - Introduction to Systems Programming Page
Dereferencing pointers
- *pointer // dereference a pointer
- *pointer = value; // dereference / assign
- dereference: access the memory referred to by a pointer
43
#include <stdio.h> int main(int argc, char **argv) { int x = 42; int *p; // p is a pointer to an integer p = &x; // p now stores the address of x printf("x is %d\n", x); *p = 99; printf("x is %d\n", x); return 0; }
CMPSC 311 - Introduction to Systems Programming Page
& and *
- &foo // “address of” foo
- *pointer // dereference a pointer
- *pointer = value; // dereference / assign
int x = 42; // x now contains the value 42 int *p; // p is a pointer to an integer p = &x; // p now contains the address of x printf("x is %d\n", x); *p = 99; // store 99 where p points to printf("x is %d\n");
CMPSC 311 - Introduction to Systems Programming Page
Something curious
- Let’s try running this program several times:
#include <stdio.h> int main(int argc, char **argv) { int x = 1; int *p = &x; printf("&x: %p; p: %p; &p: %p\n", &x, p, &p); return 0; } [butler]> ./asr &x: 0xbfa521dc; p: 0xbfa521dc; &p: 0xbfa521d8 [butler]> ./asr &x: 0xbf836f5c; p: 0xbf836f5c; &p: 0xbf836f58 [butler]> ./asr &x: 0xbfea39dc; p: 0xbfea39dc; &p: 0xbfea39d8
CMPSC 311 - Introduction to Systems Programming Page
ASLR
- Linux uses address-space
randomization for added security
- linux randomizes:
- base of stack
- shared library (mmap) location
- makes stack-based buffer
- verflow attacks tougher
- makes debugging tougher
- google “disable linux address
space randomization”
46
0x00000000 0xFFFFFFFF
OS kernel [protected] stack shared libraries heap (malloc/free) read/write segment .data, .bss read-only segment .text, .rodata