CS 241 Section Week #2 2/4/10
2 Topics This Section MP1 overview Part1: Pointer manipulation Part2: Basic dictionary structure implementation Review of strings Memory allocation and free Process creation using fork()
3 MP1 part1: Pointers mp1-functions.c contains 12 different functions, each of which print out “Illinois” Edit part1.c to print out 12 "Illinois" lines To print a "Illinois" line, formulate the parameter(s) to the corresponding function appropriately Do NOT modify mp1-functions.c
4 Review of Pointers The & operator creates a pointer to a variable int x; int *xptr = &x; // xptr = 0xAF981DF8 The * operator reads the data which a pointer references int y = *xptr; // y = x
5 Pointer arithmetic char a[8]; /* array of bytes */ char *p = a; /* p, a: 0xAF99EFDC */ char *q = a+3; /* q: 0xAF99EFDF */ ( a+3 and &a[3] are the same )...
6 Pointer arithmetic (2) int b[2]; /* array of 4-byte words */ int *q = b+1; /* q: 0xAF99EFE0 */ char *r = &b[1]; /* r: 0xAF99EFE0 */...
7 MP1 part2: Dictionary data structure Implement a basic dictionary data structure Defined in libdictionary/libdictionary.h typedef struct _dictionary_t{ char *key, *value; struct _dictionary_t *next; } Host: key = Host value =
8 Dictionary files part2.c – Provides a simple program to populate the dictionary from a file libdictionary/libdictionary.h – Contains definition of the dictionary data structure ( struct dictionary_t ) and its six functions libdictionary/libdictionary.c – Implement the functions here
9 Dictionary functions int dictionary_init(dictionary_t *d) int dictionary_add(dictionary_t *d, char *key, char *value) void dictionary_remove(dictionary_t *d, char *key) int dictionary_parse(dictionary_t *d, char *key_value) void dictionary_print(dictionary_t *d) void dictionary_destroy(dictionary_t *d)
10 Dictionary functions int dictionary_init(dictionary_t *d) – Initialize data structure `d` – Return value 0: if initialization successful Non-zero integer: otherwise int dictionary_destroy(dictionary_t *d) – Remove all entries from `d` (uses dictionary_remove function) – Free up any other memory associated with `d`
11 Dictionary functions int dictionary_add(dictionary_t *d, char *key, char *value) – add (key, value) pair to dictionary `d` – DO NOT edit `d` if the key already exists – Return value non-zero integer: if key already exists 0: otherwise – Make a copy of the strings `key` and `value` before adding them to `d`
12 Dictionary functions void dictionary_remove(dictionary_t *d, char *key) – remove (key, value) pair from dictionary `d` if key exists – Free the memory allocated during dictionary_add function call
13 Dictionary functions int dictionary_parse(dictionary_t *d, char *key_value) Parameter key_value will be formatted as an HTTP header ( key_field: value_field ) Add ( key_field, value_field ) pair to `d` using dictionary_add(... ) Return value – Non-zero integer: If key_value does not comply with the format or if the call to dictionary_add(... ) fails – 0: otherwise
14 Dictionary functions void dictionary_print(dictionary_t *d) – Print out the entire contents of the dictionary `d` – Print out format printf("%s: %s", key, value); where key and value are variables storing the ( key, value ) pair of the entry
15 Review of Strings
16 Strings Sequence of zero or more characters, terminated by NULL char m[10] = “dog”; 10 bytes are allocated for array `m` Array `m` is initialized as char m[10] = {'d', 'o', 'g', '\0'};
17 String manipulation functions #include at program start Some useful functions strlen strcpy, strcat strcmp strstr
18 String Length size_t strlen(char *str) Returns the length of the string size_t is an unsigned integer type, used to define sizes of strings and (other) memory blocks String length does not include NULL char m[10] = “dog”; int len = strlen(m); // we get len = 3
19 String Initialization char *strcpy(char *dst, char const *src) char *strcat (char *dst, char const *src) Write src string to some dst location Make sure: dst string is large enough to hold result (including NULL at the end) src, dst regions do NOT overlap (undefined behavior in this case) char m[10] = “dog”; strcpy(m+1, m);
20 String Comparison int strcmp(char const *s1, char const *s2) Compares the string values of s1 and s2 lexicographically Return Value Less than 0: if s1 precedes s2 0: if s1 and s2 value are equal Greater than 0: if s1 follows s2
21 String searching char *strstr(const char *haystack, const char *needle) Returns a pointer to the first occurrence of substring needle in the string haystack Returns NULL if the substring needle is not found
22 Memory Allocation and Free
23 Memory Allocation void * malloc ( size_t size ) void *free(void *ptr) Cast the allocated memory to appropriate type before using it char *s = (char*)malloc(1024*sizeof(char)); You can only free memory which is allocated using malloc(... )
24 Using valgrind to check memory leak To run a program (./part1 ) To use valgrind ( valgrind –-leak- check=full./part1 ) valgrind output with no memory leak ==19376== ERROR SUMMARY: 0 errors from 0 contexts... ==19376== malloc/free: 1 allocs, 1 frees, 10 bytes allocated.... ==19376== All heap blocks were freed -- no leaks are possible.
25 valgrind output with memory leak Memory is allocated using malloc(... ) inside the function testmalloc(... ) ==20086== ERROR SUMMARY: 1 errors from 1 contexts... ==20086== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.... ==20086== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==20086== at 0x4022AB8: malloc (vg_replace_malloc.c:207) ==20086== by 0x : testmalloc (in /home/farhana/test) ==20086== by 0x804848A: main (in /home/farhana/test)... ==20086== LEAK SUMMARY: ==20086== definitely lost: 10 bytes in 1 blocks....
26 Processes
27 Process creation using fork() A process is an instance of a running program fork() creates a new process – In parent, fork() returns child pid – In child, fork() returns 0 The child process is identical to the parent process, except: – Process ID ( getpid() ) – Parent ID ( getppid() )
28 fork() example #include int main() { pid_t child_pid = fork(); if (child_pid < 0) {// error code perror(“Fork Failed”); return –1; } printf(“I'm process %d\n”,getpid()); if (child_pid == 0) {// child code printf(”I’m the child of parent process %d\n”, getppid()); } else { /* child_pid > 0 */// parent code printf(“I’m the parent of child process %d\n”, child_pid); } return 0; }