Lecture 3

Post on 15-Jan-2016

17 views 0 download

description

Lecture 3. Interfaces Pointers to Functions Memory bugs, File I/O Variables – the special kind. Interfaces. A definition of a set of functions that provide a coherent module (or library) Data structure (e.g., list, binary tree) User interface (e.g., drawing graphics) - PowerPoint PPT Presentation

transcript

Lecture 3

InterfacesPointers to FunctionsMemory bugs, File I/O

Variables – the special kind

Interfaces

• A definition of a set of functions that provide a coherent module (or library)– Data structure (e.g., list, binary tree)– User interface (e.g., drawing graphics)– Communication (e.g., device driver)

Interface - modularity

• Hide the details of implementing the module from its usage– Specification – “what”– Implementation – “how”

Interface – information hiding

• Hide “private” information from outside– The “outside” program should not be able to

use internal variables of the module– Crucial for modularity

• Resource management– Define who controls allocation of memory

Example interface - StrStack

• A module that allows to maintain a stack of strings

• Operations:– Create new– Push string– Pop string– IsEmpty

[See attached StrStack.h]

Implementation of StrStack

Decision #1: data structure

• Linked list• Array (static? dynamic?)• Linked list of arrays• …

We choose linked list for simplicity

Implementation of StrStack

Decision #2: Resource allocation

• Duplicated strings on stack or keep pointer to original?

• If duplicate, who is responsible for freeing them?

We choose not to duplicate --- leave this choice to user of module

Implementation of StrStack

• See StrStack.c

Using StrStackint main(){ char *Line; StrStack *Stack = StrStackNew(); while( (Line = ReadLine()) != NULL ) StrStackPush( Stack, Line );

while( (Line = StrStackPop(Stack)) != NULL ) { printf("%s\n", Line ); free( Line ); } return 0;}

Interface Principles

Hide implementation details

• Hide data structures

• Don’t provide access to data structures that might be changed in alternative implementation

• A “visible” detail cannot be later changed without changing code using the interface!

Interface Principles

Use small set of “primitive” actions

• Provide to maximize functionality with minimal set of operations

• Do not provide unneeded functions “just because you can”

Interface Principles

Don’t reach behind the back

• Do not use global variables or unexpected side effects

• Do not assume specific order of operations by the user– Such assumptions suggest the set of

primitives is wrong

Interface Principle

Consistent Mechanisms

• Do similar things in a similar way

– strcpy(dest, source)– memcpy(dest, source)

Interface Principle

Resource Management

• Free resource at the same level it was allocated

• Assumptions about resources

Pointers to functions

Pointers to Functions

• C/C++ allow to have a pointer to a function

int foo(int x){…}main(){int (*func)(int); // func is a pointer to a functionfunc = &foo;func = foo; // sameint x = (*func)(7); // same as x = foo(7)

}

Example: Numerical Integrator

b

a

k

i kab

iafdxxf1

)21

()(

a a 2a bka

Example: Numerical IntegratordoublenumericalIntegration( double a, double b,

double (*func)(double), int k ){

double delta = (b - a)/k; double Sum = 0;

for( double x = a+0.5*delta; x < b; x+= delta ) Sum += (*func)(x);

return Sum*delta;}

See NumericalIntergator.c

“Generic” interface

• Pointers to functions provide a way to write code that receives functions as arguments

• For example sorting – you can apply different comparison functions – increasing and decreasing order can be

computed using the same algorithm code– Different data types can be sorted using the

same algorithm code

Example: qsort

Library procedure:qsort( void *base,

size_t n, size_t size, int (*compare)(void const*,

void const *) );

• base – start of an array• n – number of elements• size – size of each element• compare – comparison function

Using qsort

int compareInt(void const *p, void const *q){int a = *(int const*)p; int b = *(int const*)q;if( a < b )

return -1;return a > b;

}…int array[10] = { … };qsort( array, 10, sizeof(int), compareInt );

argv & argc• To pass command line arguments to our program

we should use the following main declaration:main(int argc, char* argv[]) { ...

• Compare to main(String[] args) in java.

• Unlike java the first argument is the name of the program itself.

char** argvchar argv[][]

argv & argc: example

•$ prog1 –u danny –p 1234

argc = 5 argv[0] = “prog1” argv[1] = “-u” ... argv[4] = “1234”Always: argv[argc] = 0

File I/O•File I/O is mostly similar to stdin & stdout I/O.•Most I/O functions we encountered have a “file” counterpart which receives a FILE pointer (handle).•Examples:

getchar(void) fgetc(FILE*) scanf(const char *,...) fscanf(FILE*, const char*,...)printf(const char *,...) fprintf(FILE*, const char*,...)

•The standard streams (stdin, stdout, stderr) are also of FILE* type.

See related man pages: fprintf, fscanf, etc.

File I/O example: mywc#include <stdio.h>#include <errno.h>#include <ctype.h>main(int argc, char* argv[]) { FILE* fp; int wc = 0, ch; if (argc != 2) { printf("Usage: mywc <filename>\n"); exit(1); } errno = 0; fp = fopen(argv[1], "r");

if (fp == NULL) { perror(“”); exit(1);

}

File I/O example

while (1) { while ((ch = fgetc(fp)) != EOF && isspace(ch)) ; if (ch == EOF) break; wc++; while ((ch = fgetc(fp)) != EOF && !isspace(ch)) ; if (ch == EOF) break; } fclose(fp); printf("There are %d words in %s\n", wc, argv[1]); return 0;

}

Related man pages: fopen, fclose

Inter module variables’ scope

Static variables• Static variables in a function keep their value

for the next call to the function– Allocated on the heap

(1)void getUniqueID() {(2) static int id=0;(3) id++;(4) return id; (5)}

(6)int main() {(7) int i = getUniqueID(); //i=1(8) int j = getUniqueID(); //j=2(9)}

Static variables, cont.• “static” variable on the global scope

– Available only in the current module• “extern” variable

– Defined outside the module

file2.c

extern int y; //y from file1.cextern int x;//x defined elsewhereint myFunc() {

int y; //error…

}

file1.c

int y;static int x;int myFunc() { int x;//error …}

• C’s “const” is a qualifier that can be applied to the declaration of any variable to specify its value will not be changed.

const double e = 2.71828; const char msg[] =“Warning:”; msg[1] = ‘w’; // illegal !

C’s “const”

• Do not confuse what the “const” declaration “protects” !

– A pointer to a const variable:

int const * p = {1,2,3};p[1] = 1; // illegal!*(p+1) = 1; // illegal!p = NULL; //legal

– A const pointer to a variable:

int* const const_p = {1,2,3}; const_p[1] = 0; // legal ! const_p = NULL; // illegal!

C’s “const”

321

321

Pointer’s Syntax

• Compare:

(1)int * const p = {1,2,3}; (2)const int * p = {1,2,3};(3)int const * p = {1,2,3};

• (2) and (3) are synonyms in C to a pointer to a const array.We encourage right to left reading of declarations, to achieve better readability and avoid errors.`

• DO NOT TRY THIS AT HOME

Pointers and User Defined Types

struct Complex {int img;int real;

};Complex comp2;Complex const comp1 = comp2;

//ok,initialize using comp2Complex comp3;

comp1.img = 3; // illegal ! comp1 value is constant

comp1=comp3;// illegal ! comp1 value is constant

• All the members of a const variable are immutable !

Compare to Java’s “final”• All (methods as well as data ) are Class members. • “final” makes primitive types constants and references to objects

constant. • The values inside the referred objects are not constant !

final int LIMIT = 10;int LIMIT = 11;// illegal ! final MyObject obj1 = MyObject();

MyObject obj2 = NULL;MyObject obj3 = MyObject();obj2 = obj1;//fine, both point now to the same objectobj1 = obj3; // illegal !obj1.setSomeValue(5); // legal !

* Because All are class members you would normally use them as class constants and declare them as “static final”

“Const” Usage• The const declaration can (and should !) be used in

the definition of a function’s arguments, to indicate it would not change them:

int strlen(const char []);

• Why use ? (This is not a recommendation but a must)

– Clearer code– Avoids errors– Part of the interfaces you define!

• We will see more of “const” meaning and usage when we get to C++

Memory related bugs

• Memory leaks.• Accessing random/freed memory

addresses.

malloc_stats()• By including malloc.h you can use the malloc_stats() function which prints to the stderr information about the amount of used memory.

• Example:

. . .malloc_stats();destroyDictionary(dict);malloc_stats();. . .

malloc_stats() cntd.

With memory leak:

Arena 0: system bytes = 8140 in use bytes = 6860 . . .Arena 0: system bytes = 8140 in use bytes = 4084 . . .

Without memory leak:

Arena 0:system bytes = 8124 in use bytes = 6860. . . Arena 0:system bytes = 8124 in use bytes = 4 . . .

mtrace• Log all memory allocations to a file.

– The file name is contained in the MALLOC_TRACE environment variable.

– For example: $setenv MALLOC_TRACE ~/plab/ex1/trace

• Analyze the file to find memory leaks using the mtrace utility.

• The program must:– be compiled with –g flag– #include <mcheck.h>

mtrace exampleThe program:#include <mcheck.h>int main() { mtrace(); // later we can call muntrace() . . . muntrace(); return 0;}The log file looks like this:= Start @ [0x80486fd] + 0x804a0e0 0x8 @ [0x804887d] + 0x804a0f0 0x8 @ [0x8048c7d] + 0x804a100 0x14 @ /lib/libc.so.6:(__strdup+0x29)[0x400d7a29] + 0x804a118 0x5 @ [0x8048c7d] + 0x804a128 0x14 @ /lib/libc.so.6:(__strdup+0x29)[0x400d7a29] + 0x804a140 0x3 @ [0x8048c7d] + 0x804a150 0x14. . .

mtrace example cntd.The result of analysis (mtrace ex1 $MALLOC_TRACE)

Memory not freed: ----------------- Address Size Caller 0x0804a100 0x14 at /home/mush/plab/ex1/strBinTree.c:65 0x0804a128 0x14 at /home/mush/plab/ex1/strBinTree.c:65 0x0804a150 0x14 at /home/mush/plab/ex1/strBinTree.c:65

Memory not freed: ----------------- Address Size Caller 0x0804a118 0x5 at /lib/libc.so.6:(__strdup+0x29)[0x400d7a29] 0x0804a140 0x3 at /lib/libc.so.6:(__strdup+0x29)[0x400d7a29]

Another example:

MALLOC_CHECK_• By setting this environment variable to 0, 1, 2

we can handle some bugs, most notably freeing twice the same memory.

• Usually double free causes segmentation fault.• When MALLOC_CHECK_ is 0 freeing twice works.• When MALLOC_CHECK_ is 1 an error message is

printed. – Example:

free(): invalid pointer 0x80497b8!

• When MALLOC_CHECK_ is 2 the program (gracefully) aborts.

ElectricFence ElectricFence is a library which allows to catch

accesses to memory that was already freed, as well as off-by-one errors.

It will cause the program to segfault in the above cases, which is usually better than continue running and have unpredictable errors later.

Example:char* a = (char*)malloc(100*sizeof(char));. . . a[100] = 'c'; // ElectricFence will cause segfault

ElectricFence cntd.Example:Node* n1 = (Node*)malloc(sizeof(Node));. . . free(n1);. . . n1->x = 7; // ElectricFence will cause segfault

To use ElectricFence you should link your program with the efence library.

For example:g++ prog1.o list.o read.o -lefence

Commercial products

• Purify

• BoundsChecker

• MS’s VisualStudio