Advanced_C

download Advanced_C

of 117

Transcript of Advanced_C

  • 8/7/2019 Advanced_C

    1/117

    ADVANCED C

    -Sushma

    -Ukil

  • 8/7/2019 Advanced_C

    2/117

    Memory Management A process is an "invocation" or "activation" of a program. A program is a

    list of instructions for execution by a computer. To run the program it needs to be copied (or loaded) into the main

    computer memory and the central processing unit is told to start reading

    (and obeying) instructions taken from that area of memory. The activity of

    executing the program's instructions is called running the process.

    A portion of memory needs to be allocated to a process. The actual

    allocation of such an area of memory is a task for the loader.

    The memory area allocated to a program will usually be split into several

    sub-areas for particular.

  • 8/7/2019 Advanced_C

    3/117

    Memory management

    The code segment

    This is known as the text area in Unix parlance and simply contains the

    executable code of the program(both the program binary and any shared

    library it loads).

    If there are several processes running the same program there will still

    only be one code area as it is identical for all processes.

    The current state of a process is determined by its various data areas.

    All memory pages of code segment are marked as read-only and are

    shared with any other process using the same program file and/or shared

    library files.

    The kernel process exchange (or switch) mechanism will activate a

    particular process by indicating to the hardware where the next

    instruction is to be read from what mapping is to be used to access data

  • 8/7/2019 Advanced_C

    4/117

    Memory Management

    The data segment

    This holds the data being processed by the program, it's size is initiallydetermined by the loader from information in the binary file whichspecifies the amount of initialized data to be copied form the binary fileand the amount of un initialized space to be allocated to the process.

    On some systems the space may be initialized to zero but this is notuniversal and such areas may contain "droppings" left over from previousprocesses, a possible security problem. On older Unix systems the uninitialized space is known as bss from a PDP/11 assembler mnemonic.

    The Unix size command will give the memory requirement informationfor a binary file.

    This segment can grow as the process runs and needs more virtualmemory.

    bash$ size testhand2 92763 + 7564 + 2320 = 102647

    The above example shows that loading the binary file testhand2 willrequire 102647 bytes of memory with 92763 bytes for code, 7564 bytes

    for initialized data and 2320 bytes for non-initialized data.

  • 8/7/2019 Advanced_C

    5/117

    Memory Management

    The stack segment

    Whenever a function is called a stack frame is created tostore data related to the current invocation of the functionsuch as the return address, saved state, local copies of

    parameters and, of course, local data. The stack is normally built within the data area of the

    process and the memory allocated to the stack can beexpanded as needed.

    The stack and the arena need to be kept separate from the

    initialized and un initialized data areas, this is normallyachieved by using widely separated parts of a large virtualaddress space.

  • 8/7/2019 Advanced_C

    6/117

    Memory Management

    Heap memory

    The heap is a portion of memory allocated dynamically (as needed, atruntime) for the use of the process.

    Whenever the malloc or calloc functions are used in C for instance,they reserve space in heap memory.

    Stack

    The stackportion of memory, on the other hand, is used by the processto aid the invocation of functions.

    Every time a function is called, the process reserves a portion of stackmemory to store the values of parameters passed to the functions aswell as for results returned by the functions and the local variablesused within the functions.

    The stack is also where space for all declared data types and structures

    is reserved at compile time.

  • 8/7/2019 Advanced_C

    7/117

    Memory ManagementThe Stack And Local Variables

    The stack is used by the process to store the chain of functions which arecurrently in the middle of execution.

    Each function call causes the process to add an execution frame to thetop of the stack. This execution frame would contain the contents of CPUregisters as they were before the function call was made, the returnaddress (i.e. where in the code this function was invoked, so we can

    return there when the function returns), the parameters passed to thefunction and all local variables of the function.

    Thus, when we have function 'main' calling function 'a' which callsfunction 'b', we will have 3 frames on the stack.

    The 'allocation' of a stack frame does not require performing realmemory allocation - as the space for the stack was reserved during

    process startup. Instead, this is done by merely marking a part of thestack as containing the frame, and copying data to that frame.

    Note that local variables are "allocated" by simply advancing the stackpointer beyond their location on the stack, so allocating local variablestakes a fixed amount of time, no matter their size.

    When a function returns - its stack frame is freed by simply modifyingthe stack pointer to point below its frame.

  • 8/7/2019 Advanced_C

    8/117

    Memory ManagementThe Stack And Local Variables(cont..)

    The local variables are not initialized - they just contain the values thatwere accidentally placed in the memory locations these variablesoccupy.

    Consider a situation in which a function was called, its variables usedand given some values.

    Later the function returned, and its frame was released.

    Then, another function was called. The stack frame of this new function is located in the same place in

    memory as the frame of the former function, so the new function'slocal variables will get the values that were left there by the localvariables of the former function.

    This can explain why the values of un initialized local variables areoften neither 0, nor look like total garbage.

    Since all local variables are stored in consecutive memory on the stack,if we take a pointer to such a variable, and later on write right above orright below this pointer, we'll be modifying the contents of anotherlocal variable, or even that of the function's return address.

  • 8/7/2019 Advanced_C

    9/117

    Memory ManagementThe Stack And Local Variables(cont..)

    For example, consider the following code:int foo()

    {

    int numbers[2];

    int j; j = 2;

    printf("j - %d\n", j);numbers[2] = 3;

    printf("j - %d\n", j);

    }

    During execution of this function, we first assign 2 to 'j', and thus the

    first print command will show "j - 2". Then, we try to assign a value to'numbers[2]'. However, the 'numbers' array only has 2 cells - 0 and 1.Writing into subscript '2' of this array will cause us to write just beyondthe array (which is fully located on the stack).

    The variable 'j' just happens to be stored in that location in memory, andthus, the value '3' will be actually assigned to 'j'.

    Our second print command will thus show "j - 3".

  • 8/7/2019 Advanced_C

    10/117

    Memory Management

    The Stack And Local Variables(cont..)

    Note that this assumes that the variables are stored in memory in the

    same order as they were declared inside the function's code. With some

    compilers, this might not be the case, and the out-of-range assignment

    might overwrite a different variable, or a part of the stack that does not

    hold variables, leading to other unexpected results.

    Note: local variables (as well as function parameters) might be stored

    in registers, rather than on the stack. This could be either because we

    used the 'register' keyword when declaring these variables, or because

    the compiler's optimization chose to place a variable in a register. Of

    course, such variables cannot be over-written by stack overflows.

  • 8/7/2019 Advanced_C

    11/117

    Memory Management

    Dynamic Memory Allocation

    Memory can be allocated dynamically by the calls

    malloc()

    calloc()

    realloc()

    The prototype for malloc is:

    void *malloc(size_t size);

    malloc takes in a size_t and returns a void pointer.

    Why does it return a void pointer? Because it doesn't matter to mallocto what type this memory will be used for.

    Let's see an example of how malloc is used:

    int *ip;ip = malloc(5 * sizeof(int)); /* .. OR .. */

    ip = malloc(5 * sizeof(ip));

    Pretty simplistic. sizeof(int) returns the sizeof an integer on themachine, multiply by 5 and malloc that many bytes.

    The second malloc works because it sends what ip is pointing to, whichis an int.

  • 8/7/2019 Advanced_C

    12/117

    Memory Management

    Dynamic Memory Allocation(cont..) Wait... we're forgetting something. AH! We didn't check

    for return values.

    Here's some modified code:#define INITIAL_ARRAY_SIZE 5

    /* ... code ... */

    int *ip;

    if ((ip = malloc(INITIAL_ARRAY_SIZE * sizeof(int))) == NULL)

    {

    (void)fprintf(stderr, "ERROR: Malloc failed");(void)exit(EXIT_FAILURE); /* or return EXIT_FAILURE; */

    }

    Now our program properly prints an error message andexits gracefully if malloc fails.

  • 8/7/2019 Advanced_C

    13/117

    Memory Management

    Dynamic Memory Allocation(cont..) calloc works like malloc, but initializes the memory to zeroif possible.

    The prototype is:

    void *calloc(size_t nmemb, size_t size);

    bzero fills the first n bytes of the pointer to zero.

    Prototype:

    void bzero(void *s, size_t n);

    If you need to set the value to some other value (or just as ageneral alternative to bzero), you can use memset:

    void *memset(void *s, int c, size_t n);

    where you can specify c as the value to fill for n bytes ofpointer s.

  • 8/7/2019 Advanced_C

    14/117

    Memory Management

    Dynamic Memory Allocation(cont..)

    What if we run out of allocated memory during the run-time of our

    program and need to give our collection of items more memory?

    Use realloc, it's prototype:

    void *realloc(void *ptr, size_t size);

    realloc takes in the pointer to the original area of memory to enlargeand how much the total size should be.

    So let's give it a try:

    ip = realloc(ip, sizeof(ip) + sizeof(int)*5);

    Ah... Now we have some more space, by simply giving it the sizeof the

    complete array and then adding 5 spaces for ints. "I'm a genius!" you say... and then your program segfaults, core dumps

    and you get laughed at.

    STOP! This is NOT how you use realloc.

    Again. The above example is wrong. Why?

  • 8/7/2019 Advanced_C

    15/117

    Memory Management

    Dynamic Memory Allocation(cont..) First, sizeof(ip) does not give the size of the allocated space originally

    allocated by malloc (or a previous realloc).

    Using sizeof() on a pointer only returns the sizeof the pointer, which isprobably not what you intended.

    Also, what happens if the realloc on ip fails? ip gets set to NULL, and

    the previously allocated memory to ip now has no pointer to it. Now we have allocated memory just floating in the heap without a

    pointer. This is called a memory leak. This can happen from sloppyrealloc's and not using free on malloc'd space. So what is the correctway? Take this code for example:

    int *tmp;

    if ((tmp = realloc(ip, sizeof(int) * (INITIAL_ARRAY_SIZE + 5))) ==NULL)

    {

    /* Possible free on ip? Depends on what you want */

    fprintf(stderr, "ERROR: realloc failed");

    }ip = tmp;

  • 8/7/2019 Advanced_C

    16/117

    Memory ManagementDynamic Memory Allocation(cont..)

    Now we are creating a temporary pointer to try a realloc. If it fails, then

    it isn't a big problem as we keep our ip pointer on the original memory

    space.

    Also, note that we specified the real size of our original array and now

    are adding 5 more ints (so 4bytes*(5+5) = 40bytes, on a typical 32-bit

    machine). Now that we can malloc, calloc, and realloc we need to be able to free

    the memory space if we have no use for it anymore. Like we mentioned

    above, any memory space that loses its pointer or isn't free'd is a

    memory leak.

    So what's the prototype for free? Here it is:void free(void *ptr);

    free simply takes in a pointer to free. Not challenging at all. Note that

    free can take in NULL, as specified by ANSI.

  • 8/7/2019 Advanced_C

    17/117

    Memory Management

    Assigning memory to segments

    Compiler and assembler generate an object file (containing code and

    data segments) from each source file

    Linker combines all the object files for a program into a singleexecutable object file, which is complete and self-sufficient

    Loader (part of OS) loads an executable object file into memory at

    location(s) determined by the operating system

    Program (as it runs) uses new and malloc to dynamically allocate

    memory, gets space on stack during function calls

  • 8/7/2019 Advanced_C

    18/117

    Memory Management

    LinkingFunctions of a linker:

    Combine all files and libraries of a program

    Regroup all the segments from each file together (one big data segment,etc.)

    Adjust addresses to match regrouping Result is an executable program

    Contents of object files:

    File header size and starting address(in memory) of each segment

    Segments for code and initialized data Symbol table (symbols, addresses)

    External symbols (symbols, location)

    Relocation information (symbols, location)

    Debugging information

    For UNIX details, type man a.out

  • 8/7/2019 Advanced_C

    19/117

    Memory Management

    Why is Linking Difficult? When assembler assembles a file, it may find external references

    symbols it doesnt know about (e.g., printf, scanf)

    Compiler just puts in an address of 0 when producing the object code

    Compiler records external symbols and their location (in object file) in

    a crossreference list, and stores that list in the object file Linker must resolve those external references as it links the files

    together

    Compiler doesnt know where program will go in memory (if

    multiprogramming, always 0 for uniprogramming)

    Compiler just assumes program starts at 0 Compiler records relocation information (location of addresses to be

    adjusted later), and stores it in the object file

  • 8/7/2019 Advanced_C

    20/117

    Memory Management

    Loading The loader loads the completed program into memory where it can be

    executed

    Loads code and initialized data segments into memory at specifiedlocation

    Leaves space for uninitialized data (bss) Returns value of start address to operating system

    Alternatives in loading

    Absolute loader loads executable file at fixed location

    Relocatable loader loads the program at an arbitrary memorylocation specified by OS (needed for multiprogramming, not foruniprogramming)

    Assembler and linker assume program will start at location 0

    When program is loaded, loader modifies all addresses by adding thereal start location to those addresses

  • 8/7/2019 Advanced_C

    21/117

    Memory Management

    Running the Program Static Memory Allocation

    Compiling, linking, and loading is sufficient for static memory

    Code, constants, static variables

    In other cases, static allocation is not sufficient:

    Need dynamic storage programmer may not know how much memorywill be needed when program runs

    Use malloc or new to get whats necessary when its necessary

    For complex data structures (e.g., trees),

    allocate space for nodes on demand

    OS doesnt know in advance which procedures will be called (would be

    wasteful to allocate space for every variable in every procedure in advance)

    OS must be able to handle recursive procedures

  • 8/7/2019 Advanced_C

    22/117

    Memory management

    Running the Program Dynamic Memory Allocation

    Dynamic memory requires two fundamental operations: Allocate dynamic storage

    Free memory when its no longer needed

    Methods vary for stack and heap

    Two basic methods of allocation: Stack (hierarchical) Good when allocation and freeing are somewhat predictable

    Typically used:

    to pass parameters to procedures

    for allocating space for local variables inside a procedure

    for tree traversal, expression evaluation,parsing, etc. Use stack operations: push and pop

    Keeps all free space together in a structured organization

    Simple and efficient, but restricted

  • 8/7/2019 Advanced_C

    23/117

    Memory Management

    Running the Program Dynamic Memory Allocation

    (cont.) Two basic methods of allocation:

    Heap

    Used when allocation and freeing are not predictable

    Typically used:

    for arbitrary list structures, complex data organizations, etc.

    Use new ormalloc to allocate space, use deleteorfreeto release space

    System memory consists of allocated areas and free areas (holes)

    Problem: eventually end up with many small holes, each too small to be useful

    This is called fragmentation, and it leads to wasted memory

    Fragmentation wasnt a problem with stack allocation, since we always add/delete

    from top of stack Solution goal: reuse the space in the holes in such a way as to keep the number of

    holes small, and their size large

    Compared to stack: more general, less efficient, more difficult to implement

  • 8/7/2019 Advanced_C

    24/117

    Strings Stings in C are stored as null character, '\0', terminated character arrays.

    This means that the length of a string is the number of characters itcontains plus one to store the null character.

    The subscripts used for the array start with zero (0).

    Common string operations include finding lengths, copying, searching,replacing and counting the occurrences of specific characters and words.

    #include needs to be included when string functions are used

    The following line declares a char array called str.

    char str[15];

    C provides fifteen consecutive bytes of memory.

    Only the first fourteen bytes are usable for character storage, because onemust be used for the string-terminating null.

    The following is a representation of what would be in RAM, if the string"Hello, world!" is stored in this array.

    Characters: H e l l o , w o r l d !

    Hex values: 48 65 6C 6C 6F 2C 20 77 6F 71 6C 64 21 00

    Subscripts: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

  • 8/7/2019 Advanced_C

    25/117

    StringsCommon String Functions

    strcpystrcpy copies a string, including the null character terminator from thesource string to the destination. This function returns a pointer to thedestination string, or a NULL pointer on error. Its prototype is:char *strcpy(char *dst, const char *src);

    strncpy

    strncpy is similar to strcpy, but it allows the number of characters tobe copied to be specified. If the source is shorter than the destination,than the destination is padded with null characters up to the lengthspecified. This function returns a pointer to the destination string, or aNULL pointer on error. Its prototype is:char *strncpy(char *dst, const char *src, size_t len);

    strcatThis function appends a source string to the end of a destinationstring. This function returns a pointer to the destination string, or aNULL pointer on error. Its prototype is:char *strcat(char *dst, const char *src);

  • 8/7/2019 Advanced_C

    26/117

    Strings

    Common String Functions(Cont..)strncatThis function appends at most N characters from the source string to theend of the destination string. This function returns a pointer to thedestination string, or a NULL pointer on error. Its prototype is:char *strncat(char *dst, const char *src, size_t N);

    strcmpThis function compares two strings. If the first string is greater than thesecond, it returns a number greater than zero. If the second string isgreater, it returns a number less than zero. If the strings are equal, itreturns 0. Its prototype is:int strcmp(const char *first, const char *second);

    strncmpThis function compares the first N characters of each string. If the firststring is greater than the second, it returns a number greater than zero. Ifthe second string is greater, it returns a number less than zero. If thestrings are equal, it returns 0. Its prototype is:int strncmp(const char *first, const char *second, size_t N);

  • 8/7/2019 Advanced_C

    27/117

    StringsCommon String Functions(Cont..)

    strlenThis function returns the length of a string, not counting the nullcharacter at the end. That is, it returns the character count of the string,without the terminator. Its prototype is:size_t strlen(const char *str);

    strchrThis function finds the first occurrence of character C in string STR,returning a pointer to the located character. It returns NULL pointerwhen there is no match

    char * strchr (char *STR, char C)

    strstr

    This function is like `strchr' but searches for string SEARCH in stringSTR, returning a pointer into the STR that is the first character of thematch found in STR. It returns NULL pointer if no match was found.If SEARCH is an empty string, it returns STR.

    char * strstr (const char *STR, const char *SEARCH)

  • 8/7/2019 Advanced_C

    28/117

    Bitwise Operators Bitwise operators apply the same operation to matching bits in value on

    each side of operator (the one's complement is unary and works only onthe value to it's right)

    Result for each bit position determined only by the bit(s) in that

    position

    Results for each operator summarized in the following table

    a

    b

    and a & b

    or a | b

    e clusive or a b

    one's complement ~a

  • 8/7/2019 Advanced_C

    29/117

    Bitwise Operators

    Shift Operators

    Operators >> and

  • 8/7/2019 Advanced_C

    30/117

    Bitwise OperatorsShift operators(contd..) Can use

  • 8/7/2019 Advanced_C

    31/117

    Bitwise Operators

    Shift operators(contd..)

    Can use >> to divide unsigned integral value by a power of two.

    1 bit divides by 2, 2 bits divides by 4, 3 bits divides by 8, n bits divides

    by 2n

    On some implementations, shifting may be much faster than dividing

    (but division makes for much clearer code)

    Shifting signed values may fail because for negative values the result

    never gets past -1:

    -5 >> 3is -1 and not 0 like -5/8

    Using right shift to divide:

    unsigned long x = 75, y;

    ...

    x >>= 2; /* x = 75 / 4 = 18 */

    y = x >> 1; /* y = ( x / 2 = 9 ) x is not changed */

  • 8/7/2019 Advanced_C

    32/117

    Structures

    Structure in C is a collection of items of different types. You can think

    of a structure as a "record" is in Pascal or a class in Java withoutmethods.

    So how is a structure declared and initialized? Let's look at anexample:

    struct student

    {char *first;

    char *last;

    char SSN[9];

    float gpa;

    char **classes;};

    struct student student_a, student_b;

    Structures :: DeclarationandSyntax

  • 8/7/2019 Advanced_C

    33/117

    Structures

    Another way to declare the same thing is:

    struct

    {

    char *first;

    char *last;

    char SSN[10];float gpa;

    char **classes;

    } student_a, student_b;

    As you can see, the tag immediately after struct is optional. But in the

    second case, if you wanted to declare another struct later, you couldn't.

  • 8/7/2019 Advanced_C

    34/117

    Structures The "better" method of initializing structs is:

    struct student_t

    {

    char *first;

    char *last;

    char SSN[10];

    float gpa;

    char **classes;

    } student, *pstudent;

    Now we have created a student_t student and astudent_t pointer. The pointer allows us greaterflexibility (e.g. Create lists of students).

    You could initialize a struct just like an arrayinitialization. But be careful, you can't initialize thisstruct at declaration time because of the pointers.

    To access fields inside struct C has a special operator forthis called "member of" operator denoted by . (period).For example, to assign the SSN ofstudent_a:

    strcpy(student_a.SSN, "111223333\0");

  • 8/7/2019 Advanced_C

    35/117

    Structures

    Nested structures

    Structures can contain other structures as members; in other words,

    structures can nest. Consider the following two structure types:

    struct first_structure_type

    {

    int integer_member;float float_member;

    };

    struct second_structure_type

    {

    double double_member;struct first_structure_type struct_member;

    };

    The first structure type is incorporated as a member of the second

    structure type.

  • 8/7/2019 Advanced_C

    36/117

    Structures

    Nested structures(Contd..)

    You can initialize a variable of the second type as follows:

    struct second_structure_type demo;

    demo.double_member = 12345.6789;

    demo.struct_member.integer_member = 5;

    demo.struct_member.float_member = 1023.17;

    The member operator . is used to access members of structures that are

    themselves members of a larger structure.

    No parentheses are needed to force a special order of evaluation

    A member operator expression is simply evaluated from left to right.

    In principle, structures can be nested indefinitely.

  • 8/7/2019 Advanced_C

    37/117

    Typedef There is an easier way to define structs or you could "alias" types you

    create.

    For example:

    typedef struct

    {

    char *first;

    char *last;char SSN[9];

    float gpa;

    char **classes;

    } student; student student_a;

    Now we get rid of those silly struct tags. You can use typedef for non-structs: typedef long int *pint32; pint32 x, y, z; x, y and z are all

    pointers to long ints. typedef is your friend. Use it.

  • 8/7/2019 Advanced_C

    38/117

    Union Unions are declared in the same fashion as structs, but have a

    fundamental difference. Only one item within the union can be used at

    any time, because the memory allocated for each item inside the unionis in a shared memory location. Why you ask? An example first:

    struct conditions

    {

    float temp;

    union feels_like{

    float wind_chill;

    float heat_index;

    }

    } today; As you know, wind_chill is only calculated when it is "cold" and

    heat_index when it is "hot". There is no need for both. So when youspecify the temp in today, feels_like only has one value, either a floatfor wind_chill or a float for heat_index.

    Types inside of unions are unrestricted, you can even use structs

    within unions.

  • 8/7/2019 Advanced_C

    39/117

    Enum What if you wanted a series of constants without creating a new type?

    Enter enumerated types. Say you wanted an "array" of months in ayear:

    enum e_months {JAN=1, FEB, MAR, APR, MAY, JUN,JUL, AUG, SEP, OCT, NOV, DEC};

    typedef enum e_months month;

    month currentmonth;currentmonth = JUN; /* same as currentmonth = 6; */

    printf("%d\n", currentmonth);

    We are enumerating the months in a year into a type called month.You aren't creating a type, because enumerated types are simplyintegers. Thus the printf statement uses %d, not %s.

    If you notice the first month, JAN=1 tells C to make the enumerationstart at 1 instead of 0.

    Note: This would be almost the same as using:

    #define JAN 1

    #define FEB 2

    #define MAR 3 /* ... etc ... */

  • 8/7/2019 Advanced_C

    40/117

    Static Variables A static variable is local to particular function. However, it is only

    initialised once (on the first call to function).

    Also the value of the variable on leaving the function remains intact.On the next call to the function the the static variable has the samevalue as on leaving.

    To define a static variable simply prefix the variable declaration withthe static keyword. For example:

    void stat(); /* prototype fn */ main() { int i; for (i=0;i

  • 8/7/2019 Advanced_C

    41/117

    Bitfields BitFields allow the packing of data in a structure. This is especially

    useful when memory or data storage is at a premium. Typical examples:

    Packing several objects into a machine word. e.g. 1 bit flags can be compacted -- Symbol tables in compilers.

    Reading external file formats -- non-standard file formats could be readin. E.g. 9 bit integers.

    C lets us do this in a structure definition by putting :bitlength after thevariable. i.e.

    struct packed_struct

    {

    unsigned int f1:1;

    unsigned int f2:1;

    unsigned int f3:1;

    unsigned int f4:1;

    unsigned int type:4;

    unsigned int funny_int:9;

    } pack;

    Here the packed_struct contains 6 members: Four 1 bit flags f1..f3, a 4 bit

    type and a 9 bit funny_int.

  • 8/7/2019 Advanced_C

    42/117

    Bitfields

    C automatically packs the above bit fields as compactly as

    possible, provided that the maximum length of the field isless than or equal to the integer word length of thecomputer. If this is not the case then some compilers mayallow memory overlap for the fields whilst other wouldstore the next field in the next word

    NOTE:

    Only n lower bits will be assigned to an n bit number. Sotype cannot take values larger than 15 (4 bits long).

    Bit fields are always converted to integer type forcomputation.

    You are allowed to mix ``normal'' types with bit fields.

    The unsigned definition is important - ensures that no bitsare used as a flag.

    Bi fi ld

  • 8/7/2019 Advanced_C

    43/117

    BitfieldsBit Fields: Practical Example

    Frequently device controllers (e.g. disk drives) and the operating systemneed to communicate at a low level. Device controllers contain several

    registers which may bepacked together in one integer We could define this register easily with bit fields:

    struct DISK_REGISTER

    {

    unsigned ready:1;

    unsigned error_occured:1;

    unsigned disk_spinning:1;

    unsigned write_protect:1;

    unsigned head_loaded:1;

    unsigned error_code:8;

    unsigned track:9; u

    nsigned sector:5;unsigned command:5; };

    To access values stored at a particular memory address,DISK_REGISTER_MEMORY we can assign a pointer of the abovestructure to access the memory via:

    struct DISK_REGISTER *disk_reg = (struct DISK_REGISTER *)

    DISK_REGISTER_MEMORY;

  • 8/7/2019 Advanced_C

    44/117

    Bitfields The disk driver code to access this is now relatively straightforward:

    /* Define sector and track to start read */disk_reg->sector = new_sector;

    disk_reg->track = new_track;

    disk_reg->command = READ; /* wait until operation done, ready will

    be true */

    while ( ! disk_reg->ready ) ; /* check for errors */if (disk_reg->error_occured)

    { /* interrogate disk_reg->error_code for error type */

    switch (disk_reg->error_code) ......

    }

    A note of caution: Portability

    Bit fields are a convenient way to express many difficult operations.

    However, bit fields do suffer from a lack of portability between

    platforms

    integers may be signed or unsigned

  • 8/7/2019 Advanced_C

    45/117

    Bitfields

    Many compilers limit the maximum number of bits in the bit fieldto the size of an integer which may be either 16-bit or 32-bit

    varieties.

    Some bit field members are stored left to right others are stored

    right to left in memory.

    If bit fields too large, next bit field may be stored consecutively inmemory (overlapping the boundary between memory locations) or

    in the next word of memory.

    If portability of code is a premium you can use bit shifting and

    masking to achieve the same results but not as easy to express or read.

    For example:

    unsigned int *disk_reg = (unsigned int *)

    DISK_REGISTER_MEMORY; /* see if disk error occured */

    disk_error_occured = (disk_reg 0x40000000) >> 31;

  • 8/7/2019 Advanced_C

    46/117

    Typecasting

    C is one of the few languages to allow coercion, that is forcing one

    variable of one type to be another type. C allows this using the castoperator (). So:int integernumber;

    float floatnumber=9.87;

    integernumber=(int)floatnumber;

    assigns 9 (the fractional part is thrown away) to integernumber.

    And:

    int integernumber=10;

    float floatnumber;

    floatnumber=(float)integernumber;

    assigns 10.0 to floatnumber.

  • 8/7/2019 Advanced_C

    47/117

    Typecasting

    Coercion can be used with any of the simple data types including char,

    so:int integernumber;

    char letter='A';

    integernumber=(int)letter;

    assigns 65 (the ASCII code for `A') to integernumber.

    Some typecasting is done automatically -- this is mainly with integercompatibility.

    A good rule to follow is: If in doubt cast.

    Another use is the make sure division behaves as requested:

    If we have two integers internumber and anotherint and we want theanswer to be a float then :

    e.g. floatnumber = (float) internumber / (float) anotherint;ensures floating point division.

    P d M

  • 8/7/2019 Advanced_C

    48/117

    Preprocessor and Macros Preprocessor includes, substitutes and selects text to form finished

    source code prior to actual compile

    #include used to copy in statements from other files, usually headerfiles with .h extension

    #define used to define macros

    simple substitution

    function-like substitution with arguments

    #undefused to remove previous definition Conditional commands used to selectively include or exclude

    statements

    #if, #elif, #else, #endif

    #ifdefand #ifndeftest if a name is defined

    defined() operator test if a name is defined

    Predefined macros

    __FILE__Source file name

    __LINE__Current source line number

    __DATE__Date compiled

    __TIME__Time compiled

    __TIMESTAMP__Compile date/time

  • 8/7/2019 Advanced_C

    49/117

    Preprocessor and Macros

    #include statement #include copies code from external files

    Files copied generally have .h file extension and considered "header

    file"

    Usually included at beginning of source module

    May be nested - included file may contain #include

    Use of brackets or quotes determines where compiler searches for the

    included file

    #include "stuff2.h"

    If file name is in quotes, looks first in the same location as the module

    with the #include statement

    #include

    If file name is in brackets, searches according to an implementation-

    defined rule.

  • 8/7/2019 Advanced_C

    50/117

    Preprocessor and Macros

    #define statement

    We already saw how #define can be used to define a simplesubstitution text for a symbol.

    Format

    #define identifier replacment-text

    #define PI 3.14159#define NUM_ROW (sizeof(ax)/sizeof(*ax))

    #define LOG_FILE "hacmp.log"

    Definition can also be function-like, with arguments

    #define identifier(arg1,arg2) repl-text

    When macro is invoked, argument tokens appearing in themacro replacement text are replaced with the text for thatargument in the macro invocation.

  • 8/7/2019 Advanced_C

    51/117

    Preprocessor and Macros

    #ifdirective

    #ifis followed by a intger constant expression. If the expression is not zero, the statement(s) following the #ifare

    compiled, otherwise they are ignored.

    #ifstatements are bounded by a matching #endif, #else or#elif

    Macros, if any, are expanded, and any undefined tokens are replacedwith 0 before the constant expression is evaluated

    Relational operators and integer operators may be used

    Expression examples

    #if 1

    #if 0

    #if ABE == 3

    #if ZOO < 12

    #if ZIP == 'g'

    #if (ABE + 2 - 3 * ZIP) > (ZIP - 2)

    In most uses, expression is simple relational, often equality test

    #if SPARKY == '7'

    P d M

  • 8/7/2019 Advanced_C

    52/117

    Preprocessor and Macros#else directive

    #else marks the beginning of statement(s) to be compiled if the preceding#i

    for #elif expression is zero (false) Statements following #else are bounded by matching #endif

    Examples #if OS = 'A' system( "clear" ); #else system( "cls" ); #endif

    #elifdirective#elifadds an else-if branch to a previous #if

    A series of#elif's provides a case-select type of structure

    Statement(s) following the #elifare compiled if the expression is notzero, ignored otherwise

    Expression is evaluated just like for#if

    Examples

    #if TST == 1 z = fn1( y );

    #elif TST == 2 z = fn2( y, x );

    #elif TST == 3 z = fn3( y, z, w );

    #endif ...

    #if ZIP == 'g' rc = gzip( fn );

    #elif ZIP == 'q' rc = qzip( fn );

    #else rc = zip( fn );

    #endif

  • 8/7/2019 Advanced_C

    53/117

    Preprocessor and Macros Conditonal compilation

    The following preprocessor directives are used for conditional

    compilation. Conditional compilation allows statements to be included oromitted based on conditions at compile time. #if #else #elif #endif #ifdef#ifndef

    In the following example, the printfstatements are compiled when thesymbol DEBUG is defined, but not compiled otherwise

    /* remove to suppress debug printf's*/#define DEBUG

    ...

    x = ....

    #ifdef DEBUG

    printf( "x=%d\n" );

    #endif...

    y = ....;

    #ifdef DEBUG

    printf( "y=%d\n" );

    #endif ...

  • 8/7/2019 Advanced_C

    54/117

    Pointers

    Pointers provide an indirect method of accessing variables.

    You may be wondering, what is the point of this (no pun intended)? Why don't I just make all variables without the use of pointers?

    It's because sometimes you can't.

    What if you needed an array of ints, but didn't know the size of thearray before hand?

    What if you needed a string, but it grew dynamically as the programran?

    They are all solved through the use of pointers. Pointers are alsoessential in creating larger custom data structures, such as linked lists.

    A pointer when declared is just a reference. DECLARING APOINTER DOES NOT CREATE ANY SPACE FOR THE

    POINTER TO POINT TO. We will tackle this dynamic memoryallocation issue later.

    A pointer is a reference to an area of memory in the heap. The heap isa dynamically allocated area of memory when the program runs.

    P i t

  • 8/7/2019 Advanced_C

    55/117

    Pointers Pointers are declared by using the * infront of the variable identifier.

    For example:

    int *ip;float *fp = NULL;

    char *a;

    This declares a pointer, ip, to an integer.

    Let's say we want ip to point to an integer.

    The second line declares a pointer to a float, but initializes the pointer topoint to the NULL pointer. The NULL pointer points to a place inmemory that cannot be accessed. NULL is useful when checking forerror conditions and many functions return NULL if they fail.

    Third line declares pointer to a char.

    int x = 5;

    int *ip;

    ip = &x;

    The operator is to specify the address-ofx. Thus, the pointer, ip ispointing to x by assigning the address of x.

    The * dereferences the pointer to the value.

    So, printf("%d %d\n", x, *ip); would print 5 5 to the screen.

    P i t

  • 8/7/2019 Advanced_C

    56/117

    Pointers

    What is the output of this program?

    main()

    {int i = 54;

    float a = 3.14;

    char *ii, *aa;ii = & i;

    aa = & a;

    printf(\nAddress contained in ii = %u, ii);

    printf(\nAddress contained in ii = %u, ii);

    printf(\nValue at the address contained in ii = %d, *ii);printf(\nValue at the address contained in ii = %d, *aa);

    }

    Binary equivalent of 54

    2008 2009

    i

    Binary equivalent of 3.14

    a

    7006 7007 7008 7009

  • 8/7/2019 Advanced_C

    57/117

    Pointers

    Output

    ii and aa are declared as char pointers. Still the statements ii = i and aa= a work.

    The addresses 2008 and 7006 get stored in ii and cc which are printed

    through the first two printf()s.

    However the program falters at the next two printf()s.

    This is so since ii is a character pointer *ii gives value at address 2008and not the one present in 2008 and 2009.

    Similarly *aa gives the value at 7006 and not the one contained in 7006,

    7007, 7008 and 7009.

    Moral is if you wish to access an integer value stored in a variable using

    its address its necessary that the address be stored in an integer pointer.Likewise if you wish to access a float value stored in a variable using

    its address its necessary to store the address in a float pointer.

    P i t

  • 8/7/2019 Advanced_C

    58/117

    Pointers

    Functions Returning Pointers

    The way functions return an int, a float, a double or any other data type,it can even return a pointer.

    However, to make a function return a pointer it has to be explicitlymentioned in the calling function as well as in the function declaration.

    Example:

    main()

    {

    int *p;

    int *fun();

    p=fun();

    printf(\n%u,p);

    }

    int *fun()

    {

    int i=20;

    return ( i);

    P i t

  • 8/7/2019 Advanced_C

    59/117

    Pointers

    Pointer Arithmetic

    C is one of the few languages that allows pointer arithmetic.

    In other words, you actually move the pointer reference by anarithmetic operation.

    For example:

    int x = 5,

    *ip = x; ip++;

    On a typical 32-bit machine,

    *ip would be pointing to 5 after initialization.

    But ip++; increments the pointer 32-bits or 4-bytes.

    So whatever was in the next 4-bytes, *ip would be pointing at it. Pointer arithmetic is very useful when dealing with arrays, because

    arrays and pointers share a special relationship in C.

    P i t

  • 8/7/2019 Advanced_C

    60/117

    Pointers

    Pointer Arithmetic(Contd)

    What is the output?

    main()

    {

    float *fun(float *);

    float p=23.5, *q;

    q = p;

    printf(\nq before call = %u,q);

    q = fun( p);

    printf(\nq after call = %u,q);

    }

    float *fun(float *r)

    {

    r = r+1;

    return(r);

    }

  • 8/7/2019 Advanced_C

    61/117

    Pointers

    Pointer Arithmetic(Contd)

    Output

    q before call = 5498

    q after call = 5502

    In main(), q has been declared as a float pointer. It means q is avariable capable of holding the address of a float. Through q= p the

    address of p, a float value is stored in q and then printed out through

    the printf(). This is the value before fun() is called. When fun() is

    called the address of p is sent to it and is collected in r. At this juncture

    r contains 5498. When r is incremented it would become 5502. r is a

    float pointer and on incrementing by 1 it would point to the next float

    which would be present 4 bytes hence, since every float is 4 bytes

    long. The return statement then return this address 5502 back to main()

    P i t

  • 8/7/2019 Advanced_C

    62/117

    PointersPointer Arithmetic(Contd)

    Pointers can be incremented and can be decremented as well, to point toearlier locations. Thus the following operations can beperformed

    (a) Addition of a number to a pointer. For example,

    int i=4,*j,*k;

    j=&i;

    j=j+1;

    j=j+9;

    k=j+3;(b) Subtraction of a number from a pointer. For example,

    int i=4,*j,*k;

    j=&i;

    j=j-2;

    j=j-5;

    k=j-6;

    A word of caution Do not attempt the following operations on pointers..They never work out

    (a) Addition of two pointers

    (b) Multiplying a pointer with a number

    (c) Dividing a pointer with a number

    P i t

  • 8/7/2019 Advanced_C

    63/117

    Pointers

    What is the output?main()

    {

    int a[]={10,20,30,40,50};

    int j;

    for (j=0;j

  • 8/7/2019 Advanced_C

    64/117

    Pointers

    Output

    Error message:Lvalue required in function main

    Whenever we mention the name of the array, we get its base address.

    Therefore for the first time through the loop, the printf() should print

    the value at its base address. There is no problem up to this. The

    problem lies in the next statement, a++. Since C does not perform

    bounds checking on an array, the only thing it remembers about anarray once declared is its base address. And a++ attempts to change

    this base address, which C wont allow because if it does so, it would

    be unable to remember the beginning of the array. Anything which can

    change in compilers language is called lvalue. Since value of a cannot

    be changed through ++, it flashes the error saying L value required sothat ++operator can change it.

  • 8/7/2019 Advanced_C

    65/117

    Pointers

    What is the output?main()

    {float a[]={13.24,1.5,1.5,5.4,3.5};

    Float *j,*k;

    j = a;

    k = a + 4;

    j = j * 2;

    k = k / 2;

    printf(\n%f %f,*j,*k);

    }

    Pointers

  • 8/7/2019 Advanced_C

    66/117

    Pointers

    Output

    Error message: Illegal use ofpointer infunction main

    j and k have been declared as pointer variables, whichwould contain the addresses of floats. In other words, j andk are the pointers. To begin with, the base address of thearray a[] is stored in j. The next statement is perfectlyacceptable; the address of the 4th float from the baseaddress is stored in k. The next two statements areerroneous. This is because the only operations that can be

    performed on pointers are addition and subtraction.Multiplication and division of a pointer is not allowed.Hence the error message.

    Pointers

  • 8/7/2019 Advanced_C

    67/117

    Pointers

    Pointers to structs

    Sometimes it is useful to assign pointers to structures.

    Declaring pointers to structures is basically the same as declaring anormal pointer:

    struct student *student_a;

    But how do we dereference the pointer to the struct and its fields? You

    can do it in one of two ways, the first way is: printf("%s\n", (*student_a).SSN);

    This would get the SSN in student_a. Messy and the readability ishorrible! Is there a better way? Of course, programmers are lazy! :)

    To dereference, you can use the infix operator: ->. The above example

    using the new operator: printf("%s\n", student_a->SSN);

    If we malloc'd space for the structure for *student_a could we startassigning things to pointer fields inside the structure? No. You mustmalloc space for each individual pointer within the structure that isbeing pointed to.

    Pointers

  • 8/7/2019 Advanced_C

    68/117

    Pointers

    Common error while using pointers: Using an uninitialized pointer.

    Remember, declaring a pointer variable simply allocates a cell that

    can hold a pointer - it does not place a value in the cell. So, for

    example, a code fragment like:

    {int * iptr;

    *iptr = 2;

    . . .

    }

    will attempt to place the value, 2, in the cell pointed to by iptr;

    however, iptr has not been initialized, so some garbage value will

    be used as the address of there to place the value. On some

    systems this may result in an attempt to access an illegal address,

    and a memory violation. Avoid this error by remembering to

    initialize all pointer variables before they are used.

  • 8/7/2019 Advanced_C

    69/117

    Pointers

    Common error while using pointers(Contd)

    Instead of using a pointer to an object, a pointer to a pointer

    is used.

    Consider a function, read_int(). It reads an integer and stores it

    where its argument points. The correct version is:

    void read_int(int * pn){

    scanf("%d", pn);

    }

    pn is a pointer to the object where the integer is to be stored. When

    passing the argument to scanf(), we pass the pointer, pn, NOT pn.

  • 8/7/2019 Advanced_C

    70/117

    Pointers

    Common error while using pointers(Contd)

    Confusion between the address of operator and the dereferenceoperator.

    ...

    calling_func(...)

    {

    int x;

    called_func(*x); /* should be x */ ... }

    ...

    called_func(int px) /* should be * px */

    {

    ...

    }

    A useful mnemonic aid is that the ` address of'' operator is the ``and''symbol, --- both start with letter, a.

    F nction Pointers

  • 8/7/2019 Advanced_C

    71/117

    Function Pointers

    Function Pointers are pointers, i.e. variables, which point to the

    address of a function

    Ex: int (*pt2Function) (float, char, char);

    //assign an address to the function pointer

    int DoIt (float a, char b, char c)

    {

    printf("DoIt\n);

    return a+b+c;

    }

    int DoMore(float a, char b, char c)

    {

    printf("DoMore\n";return a-b+c;

    }

    pt2Function = DoMore; //assignment

    pt2Function = DoIt; //alternative using address operator

    Function Pointers

  • 8/7/2019 Advanced_C

    72/117

    Function Pointers

    Comparing Function Pointers

    The comparison-operator (==) is used for comparing functionEx: //comparing function pointers

    if(pt2Function == DoIt)

    Printf("pointer points to DoIt\n);"

    Calling a Function using a Function Pointer

    There are two alternatives to call a function using a function pointer:

    Use the name of the function pointer instead of the name of thefunction.

    Explicitly dereference it.

    Ex: //calling a function using a function pointer

    int result1 = pt2Function (12, 'a', 'b');

    int result2 = (*pt2Function) (12, 'a', 'b');

    Function Pointers

  • 8/7/2019 Advanced_C

    73/117

    Function Pointers

    Returning a Function Pointer

    A function pointer can be a function's return value.float (*GetPtr1(const char opCode))(float, float)

    {

    if(opCode == '+')

    return &Plus;

    if(opCode == '-')return &Minus; }

    // using a typedef

    typedef float(*pt2Func)(float, float);

    pt2Func GetPtr2(const char opCode)

    {

    if(opCode == '+')

    return &Plus;

    if(opCode == '-')

    return &Minus;

    }

  • 8/7/2019 Advanced_C

    74/117

    Function Pointers

    // execute example code

    void Return_A_Function_Pointer()

    {Printf( "Executing 'Return_A_Function_Pointer\n');

    float (*pt2Function)(float, float); // define a function pointer

    pt2Function=GetPtr1('+'); // get function pointer from function

    'GetPtr1Printf(pt2Function(2, 4) \n); // call function using the

    pointer

    Printf(pt2Function=GetPtr2('-') \n); // get function pointerfrom function 'GetPtr2

    Printf(pt2Function(2, 4)\n); // call function using the pointer

    }

    Function pointers are usually used

    (a) In writing memory resident programs

    (b) In writing viruses or vaccines to remove the viruses

    Function Pointers

  • 8/7/2019 Advanced_C

    75/117

    Function Pointers

    Arrays of Function Pointers// 2.8 How to Use Arrays of Function Pointerstypedef int(*pt2Function)(float, char, char);

    // illustrate how to work with an array of function pointers

    Void Array_Of_Function_Pointers()

    {

    printf("Executing Array_Of_Function_Pointers\n);// is an array with 10 pointers to functions which return an int //

    and take a float and two char

    pt2Function funcArr[10]; // assign the function's address - 'DoIt' and'DoMore' are suitable functions // like defined above in 2.1-4

    funcArr[0] = &DoIt;

    funcArr[1] = &DoMore; /* more assignments */

    // calling a function using an index to address the function pointer

    printf(funcArr[1](12, 'a', 'b')\n);

    printf(funcArr[0](12, 'a', 'b')\n);

    }

    Libraries

  • 8/7/2019 Advanced_C

    76/117

    Libraries

    A " library'' is simply a file containing compiled code (and

    data) that is to be incorporated later into a program

    A library is a file containing several object files, that can

    be used as a single entity in a linking phase of a program.

    Libraries allow programs to be more modular, faster to

    recompile, and easier to update. Normally the library is indexed, so it is easy to find

    symbols (functions, variables and so on) in them.

    For this reason, linking a program whose object files are ordered

    in libraries is faster than linking a program whose object files are

    separate on the disk.

    Also, when using a library, we have fewer files to look for and

    open, which even further speeds up linking.

    Lib i

  • 8/7/2019 Advanced_C

    77/117

    Libraries can be divided into three types: static libraries

    Collections of object files that are linked into the programduring the linking phase of compilation.

    shared libraries

    Linked into the program in two stages. First, during compile time, the linker verifies that all the

    symbols (functions, variables and the like) required by theprogram, areeither linked into theprogram, or in one of itsshared libraries.

    When theprogram is started, a program in the system

    (called a dynamic loader) checks out which shared librarieswere linked with theprogram, loads them to memory, andattaches them to the copy of theprogram in memory

    dynamically loaded (DL) libraries. Loaded and used at any time while a program is running

    Libraries

    Static Libraries

  • 8/7/2019 Advanced_C

    78/117

    Static Libraries

    Static libraries are simply a collection of ordinary

    object files Conventionally, static libraries end with the ``.a''

    suffix.

    This collection is created using the ar (archiver)

    program. Static libraries permit users to link to programs

    without having to recompile its code, savingrecompilation time.

    Static libraries are often useful for developers ifthey wish to permit programmers to link to theirlibrary, but don't want to give the library sourcecode

    Static Libraries

  • 8/7/2019 Advanced_C

    79/117

    Static Libraries

    To create a static library, or to add

    additional object files to an existing static

    library, command to be used is:

    ar rcs my_library.a file1.o file2.o

    Static library can be used by invoking it as partof the compilation and linking process when

    creating a program executable.

    If gcc(1) is used to generate executable, -l option

    can be used to specify the link the library

    Shared Libraries

  • 8/7/2019 Advanced_C

    80/117

    Shared Libraries

    Shared libraries are libraries that are loaded by

    programs when they start. When a shared library is installed properly, all

    programs that start afterwards automatically usethe new shared library

    Every shared library has a special name called the``soname''.

    The soname has the prefix ``lib'', the name of thelibrary, the phrase ``.so'', followed by a period and

    a version number that is incremented wheneverthe interface changes (as a special exception, thelowest-level C libraries don't start with ``lib'').

    Shared Libraries

  • 8/7/2019 Advanced_C

    81/117

    A fully-qualified soname includes as a prefix the directory

    it's in; on a working system a fully-qualified soname issimply a symbolic link to the shared library's ``real name''.

    /usr/lib/libreadline.so.3 is a fully-qualified soname

    Shared libraries must be placed somewhere in the

    filesystem The GNU standards recommend installing by default all

    libraries in /usr/local/lib

    What's the advantage of creating executables using

    Dynamic Libraries? The executable is much smaller thanwith static libraries. If it is a standard library that can be

    installed, there is no need to compile it into the executable

    at compile time!

    Shared Libraries

  • 8/7/2019 Advanced_C

    82/117

    Shared Libraries

    Creating shared or dynamic libraries is simple also.Using the previous example, to create a shared library

    gcc -fPIC -c objfile1.c

    gcc -fPIC -c objfile2.c

    gcc -fPIC -c objfile3.c

    gcc -shared -o libmylib.so objfile1.o objfile2.o objfile3.o

    The -fPIC option is to tell the compiler to create PositionIndependent Code (create libraries using relativeaddresses rather than absolute addresses because these

    libraries can be loaded multiple times). The -shared option is to specify that an architecture-

    dependent shared library is being created.

    However, not all platforms support this flag

  • 8/7/2019 Advanced_C

    83/117

    Shared Libraries

    Now we have to compile the actualprogram using the libraries:

    gcc -o foo -L. -lmylib foo.o

    Notice it is exactly the same as creatinga static library. Although, it is compiledin the same way, none of the actuallibrary code is inserted into theexecutable, hence the dynamic/sharedlibrary.

    Note: You can automate this processusing Makefiles!

    Dynamic Loaded Libraries

  • 8/7/2019 Advanced_C

    84/117

    Dynamic Loaded Libraries

    Dynamically loaded (DL) libraries are

    libraries that are loaded at times other thanduring the startup of a program. They'reparticularly useful for implementing pluginsor modules, because they permit waiting toload the plugin until it's needed

    They're also useful for implementinginterpreters that wish to occasionally

    compile their code into machine code anduse the compiled version for efficiencypurposes, all without stopping

    Lib i

  • 8/7/2019 Advanced_C

    85/117

    Libraries The key to making your program work with

    dynamic libraries is through theLD_LIBRARY_PATH enviornment variable.

    To display this variable, at a shell: echo$LD_LIBRARY_PATH Will display this variable ifit is already defined.

    If it isn't, you can create a wrapper script foryour program to set this variable at run-time.Depending on your shell, simply use setenv(tcsh, csh) or export (bash, sh, etc)commands.

    If you already have LD_LIBRARY_PATHdefined, make sure you append to thevariable, not overwrite it!

  • 8/7/2019 Advanced_C

    86/117

    Libraries

    For example:

    setenv LD_LIBRARY_PATH/path/to/library:${LD_LIBRARY_PATH}

    would be the command you would use if you had tcsh/csh and alreadyhad an existing LD_LIBRARY_PATH.

    If you didn't have it already defined, just remove everything right ofthe :.

    An example with bash shells:

    exportLD_LIBRARY_PATH=/path/to/library:${LD_LIBRARY_PATH}

    Again, remove the stuff right of the : and the : itself if you don'talready have an existing LD_LIBRARY_PATH.

    If you have administrative rights to your computer, you can install theparticular library to the /usr/local/lib directory and permanently add anLD_LIBRARY_PATH into your .tcshrc, .cshrc, .bashrc, etc. file.

    Make command

  • 8/7/2019 Advanced_C

    87/117

    Make command

    Make allows a programmer to easilykeep track of a project by maintainingcurrent versions of their programs from

    separate sources. Make can automate various tasks for

    not only compiling proper branch ofsource code from the project tree, but

    helping to automate other tasks, suchas cleaning directories, organizingoutput, and even debugging.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    88/117

    Make and Makefiles

    Make reads its instructions from text files.

    An initialization file is read first, followed by the makefile.

    The initialization file holds instructions for all makes and is used tocustomize the operation of Make.

    Make automatically reads the initialization file whenever it starts up.Typically the initialization file is named make.ini and it resides in the

    directory of make.exe and mkmf.exe. The name and location of theinitialization file is discussed in detail on Page .

    The makefile has instructions for a specific project. The default name ofthe makefile is literally makefile, but the name can be specified with acommand-line option.

    With a few exceptions, the initialization file holds the same kind of

    information as does a makefile. Both the initialization file and themakefile are composed of the following components: comments,dependency lines, directives, macros, response files, rules and shelllines.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    89/117

    Make and MakefilesContinued Makefile Lines

    Lines in the makefile can be very long. For easier reading a long line can bebroken up by putting \enter as the last characters of this line and the rest ofthis (logical) line on the next (physical) line of the makefile. For example:

    first_part_of_line second_part_of_line

    is the same as:

    first_part_of_line\

    second_part_of_line

    Comments

    The simplest makefile statement is a comment, which is indicated by thecomment character #. All text from the comment character to the end of theline is ignored. Here is a large comment as might appear in a makefile todescribe its contents:

    #

    #Makefile for Opus Make 6.1

    #

    # Compiler: Microsoft C 6.0

    # Linker: Microsoft Link 5.10

    The comment character could also be used at the end of another makefilestatement:

    somemakefilestatement# a comment

    Make and Makefiles

  • 8/7/2019 Advanced_C

    90/117

    Make and MakefilesComments and Continued Makefile Lines

    If \enter appears on a commented line, the comment acts until the end of the line andthe following line is still continued. For example:

    line_one \line_two#more_line_two \

    line_three

    is the same as:

    line_one line_twoline_three

    Rules

    A rule tells Make both when and how to make a file. As an example, suppose yourproject involves compiling source files main.c and io.c then linking them to produce theexecutable project.exe. Withholding a detailed explanation for a bit, here is a makefileusing Borland C which will manage the task of making project.exe:

    The ExampleMakefile

    project.exe : main.obj io.obj

    tlink c0s main.obj io.obj, project.exe,, cs /Lf:\bc\lib

    main.obj : main.cbcc ms c main.c

    io.obj : io.c

    bcc ms c io.c

    This makefile shows three rules, one each for making project.exe, main.obj, and io.obj.The rules as shown above are called explicit rules since they are supplied explicitly inthe makefile. Make also has inference rules that generalize the make process.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    91/117

    Make and MakefilesDependency Lines: When to Build a Target

    The lines with the colon : in them are called dependencylines. They determine when the target is to be rebuilt.

    To the left of the colon is the target of the dependency. Tothe right of the colon are the sources needed to make thetarget. A dependency line says the target depends on the

    sources. For example, the line:project.exe : main.obj io.obj

    states that project.exe depends on main.obj and io.obj. Atrun time Make compares the time that project.exe was lastchanged to the times main.obj and io.obj were last changed.

    If either source is newerthan project.exe, Make rebuildsproject.exe. The last-changed time is the target's time as itappears in the file-system directory. This time is also knownas the target's timestamp.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    92/117

    Make and MakefilesTheMake Process is Recursive

    It is a basic feature of Make that a target's sources are made before thetimestamp comparison occurs. The line:

    project.exe : main.obj io.obj

    implies make main.obj and io.obj before comparing their timestampswith project.exe. In turn:

    main.obj : main.c

    says make main.c before comparing its timestamp with main.obj.You can see that if main.c is newer than main.obj, main.obj will berebuilt. Now main.obj will be newer than project.exe, causingproject.exe to be rebuilt.

    Additional Dependencies

    In C and in other programming languages it is possible to include thecontents of a file into the file currently being compiled. Since thecompiled objectdepends on the contents of the included file, we addthe included file as a source of the objectfile.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    93/117

    Make and Makefiles Assume each of main.c and io.c include def.h. We can either change

    two dependency lines in the makefile:

    main.obj : main.c becomes main.obj : main.c def.hio.obj : io.c becomes io.obj : io.c def.h

    or add a new line which lists only the additional dependencies:

    main.obj io.obj : def.h

    Notice that there are two targets on the left of the colon. This linemeans that both main.obj and io.obj depend on def.h. Either of these

    methods are equivalent. The example makefile now looks like:project.exe : main.obj io.obj

    tlink c0s main.obj io.obj, project.exe,, cs /Lf:\bc\lib

    main.obj : main.c

    bcc ms c main.c

    io.obj : io.c

    bcc ms c io.c

    main.obj io.obj : incl.h

    Make and Makefiles

  • 8/7/2019 Advanced_C

    94/117

    Make and MakefilesShell Lines: How to Build a Target [Top]

    The indented lines that follow each dependency line are called shelllines. Shell lines tell Make how to build the target. For example:

    project.exe : main.obj io.obj

    tlink c0s main.obj io.obj, project.exe,, cs /Lf:\bc\lib

    tells Make that making project.exe requires running the program tlinkto link main.obj and io.obj. This shell line would be run only if

    main.obj or io.obj was newer than project.exe. For tlink, c0s is the small model start-up object file and the cs is the

    small model library. The /Lf:\bc\lib flag tells tlink that the start-upobject file and library files can be found in the f:\bc\lib directory.

    A target can have more than one shell line, listed one after the other,such as:

    project.exe : main.obj io.obj

    echo Linking project.exe

    tlink c0s main.obj io.obj, project.exe,, cs /Lf:\bc\lib >tlink.out

    The first line shows that command processor commands can beexecuted by Make. The second line shows redirection of output, where

    the output of the tlink program is redirected to the tlink.out file.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    95/117

    After each shell line is executed, Make checks the shell line exitstatus. By convention, programs return a 0 (zero) exit status if theyfinish without error and non-zero if there was an error. The first shellline returning a non-zero exit status causes Make to display themessage:

    OPUS MAKE: Shell line exit status exit_status. Stop.

    This usually means the program being executed failed. Some

    programs return a non-zero exit status inappropriately and you canhave Make ignore the exit status by using a shell-lineprefix. Prefixesare characters that appear before the program name and modify theway Make handles the shell line. For example:

    project.exe : main.obj io.obj

    tlink c0s main.obj io.obj, project.exe,, cs /Lf:\bc\lib

    The prefix tells Make to ignore the exit status of shell line. If theexit status was non-zero Make would display the message:

    OPUS MAKE: Shell line exit status exit_status (ignored)

    Make and Makefiles

  • 8/7/2019 Advanced_C

    96/117

    Make and Makefiles

    Macros

    The example makefile is reproduced here:project.exe : main.obj io.obj

    tlink c0s main.obj io.obj, project.exe,, cs /Lf:\bc\lib

    main.obj : main.c

    bcc ms c main.c

    io.obj : io.cbcc ms c io.c

    main.obj io.obj : def.h

    We see that the text main.obj io.obj occurs repeatedly. To cut downon the amount of repeated text, we can use a macro definition to assign asymbol to the text.

    Defining Macros in theMakefile

    A macro definition line is a makefile line with a macro name, an equalssign =, and a macro value. In the makefile, expressions of the form$(name) or ${name} are replaced with value. If the macro name is asingle letter, the parentheses or braces are optional (i.e. $X, $(X) and

    ${X} all mean the value of macro X).

    Make and Makefiles

  • 8/7/2019 Advanced_C

    97/117

    Make and Makefiles Here is the above example written with the introduction of four macros:

    OBJS = main.obj io.obj

    MODEL = sCC = bcc

    CFLAGS = m$(MODEL)

    project.exe : $(OBJS)

    tlink c0$(MODEL) $(OBJS), project.exe,, c$(MODEL) /Lf:\bc\lib

    main.obj : main.c$(CC) $(CFLAGS) c main.c

    io.obj : io.c $(CC) $(CFLAGS) c io.c

    $(OBJS) : incl.h

    The value of the OBJS macro is the list of object files to be compiled.The macro definitions for MODEL, CC and CFLAGS were introduced

    so that it is easier to change the compiler memory model, name of the Ccompiler and its options.

    Make automatically imports environment variables as macros, so you canreference an environment variable such as PATH with the makefileexpression $(PATH).

    Make and Makefiles

  • 8/7/2019 Advanced_C

    98/117

    Defining Macros on the Command Line

    Macros can be defined on the Make command line. For example:

    make CFLAGS=ms

    would start up Make and define the macro CFLAGS with the value ms. Macros defined on the command line take precedence overmacros of the same name defined in the makefile.

    If a command-line macro contains spaces, it must be enclosed in

    double quotes as in:make "CFLAGS=-ms -z -p"

    Run-TimeMacros

    Make defines some special macros whose values are set dynamically.

    These macros return information about the current target being built.As examples, the .TARGET macro is name of the current target, the.SOURCE macro is the name of the inferred source (from an inferencerule) or the first of the explicit sources and the .SOURCES macro isthe list of all sources.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    99/117

    Make and Makefiles

    Using run-time macros the example can be written:OBJS = main.obj io.obj

    CC = bcc

    MODEL = s

    CFLAGS = m$(MODEL)

    project.exe : $(OBJS)

    tlink c0$(MODEL) $(OBJS), $(.TARGET),, c$(MODEL)/Lf:\bc\lib

    main.obj : main.c

    $(CC) $(CFLAGS) c $(.SOURCE)

    io.obj : io.c

    $(CC) $(CFLAGS) c $(.SOURCE)$(OBJS) : incl.h

    As you can see, the shell lines for updating main.obj and io.obj areidentical when run-time macros are used. Run-time macros areimportant for generalizing the build process with inference rules.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    100/117

    Macro Modifiers

    Macros are used to reduce the amount of repeated text. They are alsoused in inference rules to generalize the build process. We often wantto start with the value of a macro and modify it in some manner. Forexample, to get the list of source files from the OBJS macro we can do:

    SRCS = $(OBJS,.obj=.c)

    This example uses the from=to macro modifier to replace the from

    text in the expansion of OBJS with the to

    text. The result is that$(SRCS) is main.c io.c. In general, to modify a macro expand itwith:

    $(name,modifier[,modifier...])

    Each modifieris applied in succession to the expanded value ofname.Each modifier is separated from the next with a comma.

    Filename Components

    There is a set of macro modifiers for accessing parts of file names. Forexample, with the macro definition:

    SRCS = d:\src\main.c io.asm

    Make and Makefiles

  • 8/7/2019 Advanced_C

    101/117

    Some of the modifiers are:

    Modifier, and description Example Value

    D, the directory $(SRCS,D) d:\src .E, the extension (or suffix) $(SRCS,E) .c .asm

    F, the file name $(SRCS,F) main.c io.asm

    Tokenize

    Another modifier is the Wstr modifier, which replaces whitespacebetween elements of the macro with str, a string. The strcan be a mixof regular characters and special sequences, the most importantsequence being \n which represents a newline character (like hittingthe enter key). For example:

    $(OBJS,W space +\n) is main.obj +

    io.obj

    Other Modifiers

    Other modifiers include: @ (include file contents), LC (lowercase), UC (upper case), M (member) and N (non-member). TheM and N modifiers and the S (substitute) modifier use regularexpressions for powerful and flexible pattern-matching. See Page formore information on all macro modifiers.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    102/117

    Inference Rules

    Inference rules generalize the build process so you don't have to give an

    explicit rule for each target. As an example, compiling C source (.cfiles) into object files (.obj files) is a common occurrence. Rather thanrequiring a statement that each .obj file depends on a like-named .c file,Make uses an inference rule to infer that dependency. The sourcedetermined by an inference rule is called the inferred source.

    Inference rules are rules distinguished by the use of the character %

    in the dependency line. The % (rule character) is a wild card,matching zero or more characters. As an example, here is an inferencerule for building .obj files from .c files:

    %.obj : %.c

    $(CC) $(CFLAGS) c $(.SOURCE)

    This rule states that a .obj file can be built from a corresponding .c filewith the shell line $(CC) $(CFLAGS) c $(.SOURCE). The .c and.obj files share the same root of the file name.

    When the source and target have the same file name except for theirextensions, this rule can be specified in an alternative way:

    .c.obj :

    $(CC) $(CFLAGS) c $(.SOURCE)

    Make and Makefiles

  • 8/7/2019 Advanced_C

    103/117

    The alternative form is compatible with Opus Make prior to

    this version and with other make utilities and is discussed inmore detail on Page .

    Make predefines the %.obj : %.c inference rule as listedabove so the example we have been working on nowbecomes much simpler:

    OBJS = main.obj io.objCC = bcc

    MODEL = s

    CFLAGS = m$(MODEL)

    project.exe : $(OBJS)

    tlink c0$(MODEL) $(OBJS), $(.TARGET),, c$(MODEL)/Lf:\bc\lib

    $(OBJS) : incl.h

    Make and Makefiles

  • 8/7/2019 Advanced_C

    104/117

    Response Files

    For MS-DOS, OS/2 Win95 there is a rather severe restriction on thelength of a shell line with the result that the shell line is often too shortfor many compilers and far too short for linkers and librarians.

    To overcome this restriction many programs can receive command-lineinput from a response file. Opus Make has two kinds of support forresponse files: automatic response files, where Make decides when tobuild a response file or; inline response files, where you write responsefile-creating statements directly in the makefile.

    Automatic Response Files

    Make has predefined support for several linkers, librarians andcompilers, and you can augment Make's support by writing your owndefinitions. With Make's predefined support you can just add the

    following statement to your makefile:.RESPONSE.LINK : tlink

    This tells Make that the program tlink accepts LINK-style response files.When a shell line executes tlink, Make checks if the shell line is longerthan allowed by the operating system and automatically produces aresponse file if necessary.

    Make and Makefiles

  • 8/7/2019 Advanced_C

    105/117

    Inline Response Files

    Response files can also be coded inline in your makefile. Here is thetlink shell line of the example, written to use an inline response file:project.exe : $(OBJS)

    tlink @

  • 8/7/2019 Advanced_C

    106/117

    Makefile Directives

    Makefile directives control the makefile lines Make reads at read time. Here is

    our example extended with conditional directives (%if, %elif, %else and%endif) to support both Borland and Microsoft compilers. Comments have beenadded for documentation:

    # This makefile compiles the project listed in the PROJ macro

    #

    PROJ = project # the name of the project

    OBJS = main.obj io.obj # list of object files

    # Configuration:

    #

    MODEL = s # memory model

    CC = bcc # name of compiler

    # Compiler-dependent section#

    %if $(CC) == bcc # if compiler is bcc

    CFLAGS = m$(MODEL) # $(CFLAGS) is ms

    LDSTART = c0$(MODEL) # the start-up object file

    LDLIBS = c$(MODEL) # the library

    LDFLAGS = /Lf:\bc\lib # f:\bc\lib is library directory

    Make and Makefiles

  • 8/7/2019 Advanced_C

    107/117

    %elif $(CC) == cl # else if compiler is cl

    CFLAGS = A$(MODEL,UC) # $(CFLAGS) is AS

    LDSTART = # no special start-upLDLIBS = # no special library

    LDFLAGS = /Lf:\c6\lib; # f:\c6\lib is library directory

    %else # else

    % abort Unsupported CC==$(CC) # compiler is not supported

    %endif # endif

    # The project to be built

    # $(PROJ).exe : $(OBJS)

    tlink $(LDSTART) $(OBJS), $(.TARGET),, $(LDLIBS) $(LDFLAGS)

    $(OBJS) : incl.h

    The layout of this makefile is fairly traditional macros are defined first, the

    primary target follows the macros and the extra dependency information islast.

    This example also uses the %abort directive to abort Make if the makefile doesnot support a particular compiler. Directives can also be used at run time, tocontrol the shell lines Make executes

    Makefiles

  • 8/7/2019 Advanced_C

    108/117

    Makefiles

    You can include other Makefiles by using the include directive.

    You can create conditional syntax in Makefiles, using ifdef, ifeq,ifndef, ifneq.

    You can create variables inside of Makefiles, like the $(objects)above.

    Let's use a different example. The hypothetical source tree:

    a.c__/ \__

    / \

    b.c c.c

    __/__ __\__

    / \ / \d.c e.h f.c g.c

    __ /__ __/__

    / \ / \

    h.c i.c j.h

    Makefiles

  • 8/7/2019 Advanced_C

    109/117

    Let's create a more complex, yet easier to maintain Makefile for this

    project: # Source, Executable, Includes, Library Defines

    INCL = e.h j.h

    SRC = a.c b.c c.c d.c f.c g.c h.c i.c

    OBJ = $(SRC:.c=.o)

    LIBS = -lgenEXE = moolicious

    # Compiler, Linker Defines

    CC = /usr/bin/gcc

    CFLAGS = -ansi -pedantic -Wall -O2

    LIBPATH = -L.LDFLAGS = -o $(EXE) $(LIBPATH) $(LIBS)

    CFDEBUG = -ansi -pedantic -Wall -g -DDEBUG $(LDFLAGS)

    RM = /bin/rm -f

    Makefiles

  • 8/7/2019 Advanced_C

    110/117

    Makefiles# Compile and Assemble C Source Files into Object Files

    %.o: %.c$(CC) -c $(CFLAGS) $*.c

    # Link all Object Files with external Libraries into Binaries

    $(EXE): $(OBJ)

    $(CC) $(LDFLAGS) $(OBJ)

    # Objects depend on these Libraries

    $(OBJ): $(INCL)

    # Create a gdb/dbx Capable Executable with DEBUG flags turned on

    debug:

    $(CC) $(CFDEBUG) $(SRC)# Clean Up Objects, Exectuables, Dumps out of source directory clean:

    $(RM) $(OBJ) $(EXE) core a.out

    Memory Corruption

  • 8/7/2019 Advanced_C

    111/117

    SIGSEGV This! SIGBUS That!

    We saw that some virtual memory sections aren't mapped to physicalmemory. While some of them were simply paged out, others were

    never allocated by the process. When a process runs, its virtual

    memory table is small. As it allocates more memory pages, the table

    grows. However, if the process tries to access a virtual memory

    address of a section it hasn't allocated yet, the operating system has no

    where to bring this page from. The designers of the Unix system

    decided that this situation indicates a program bug, and thus instead of

    making an automatic allocation of a memory page in such a case, they

    chose to send a signal to the process. This signal is a SEGV signal (or

    SIGSEGV), and its default signal handler prints out a "Segmentation

    violation - core dumped" message, and dumps the memory image ofthe process into a file named 'core' in the process's current directory.

    Memory Corruption

  • 8/7/2019 Advanced_C

    112/117

    Another way to cause a 'segmentation violation' is trying to access anillegal location of virtual memory. Because many invalid pointer

    problems occur with very low pointer values, the operating system doesnot allow a process to allocate a memory page for the virtual memorysection beginning with the virtual address '0'. This is what causesprograms to receive a SEGV signal when trying to dereference a NULLpointer (NULL on _most_ machine architectures is defined as '0').

    What about a BUS (or SIGBUS) signal? this signal is sent to a program

    that tries to access a non-aligned pointer. For instance, on manymachine architectures, access to 'long' (4 byte) numbers must be doneusing a memory address that divides by 4. Trying to access such anentity using an address that does not abide by this rule will cause theCPU to emit a trap. The operating system's kernel catches this trap, andthen sends a BUS signal to the program. The default signal handler for

    this signal emits a "Bus error - core dumped" message, and dumps thememory contents to a 'core' file, much like the handler for the SEGVsignal does.

    Debugging

  • 8/7/2019 Advanced_C

    113/117

    We will be using three debugging techniques:

    1. Non-interactive

    2. GNU gdb

    3. dbx

    You can debug your code by placing #ifdef DEBUG and

    corresponding #endif statements around debug code. For example:

    #ifdef DEBUG

    PRINTF(("Variables Currently Contain: %d, %f, %s\n", *pi, *pf[1],

    str));

    #endif

    You can specify a DEBUG define at compile time by issuing gcc withthe -DDEBUG command option.

    Note: This can be even further simplified into a single command called

    DPRINTF, so you don't even have to write the #ifdef #endif directives!

    Debugging using gdb

  • 8/7/2019 Advanced_C

    114/117

    gdb is a powerful program in tracking down Segmentation Faults and

    Core Dumps. It can be used for a variety of debugging purposes

    though. First thing you must do is compile with the -g option and without any

    optimization (i.e. no -O2 flag).

    Once you do that, you can run gdb . where is the name of

    the executable.

    gdb should load with the executable to run on. Now you can createbreakpoints where you want the the execution to stop. This can be

    specified with the line number in the corresponding c source file. For

    example: break 376 would instruct gdb to stop at line 376.

    You can now run the program by issuing the run command. If your

    program requires command-line options or parameters, you can specifythem with the run command. For example: run 4 -s Doc! where 4, -s,

    Doc! are the parameters.

    Debugging using gdb

  • 8/7/2019 Advanced_C

    115/117

    The program should run until the breakpoint or exit on a failure. If it

    fails before the breakpoint you need to re-examine where you should

    specify the break. Repeat the breakpoint step and rerun. If your programstops and shows you the breakpoint line, then you can step into the

    function. To step into the function use the step command. NOTE: Do

    not step into system library calls (e.g. printf). You can use the command

    next over these types of calls or over local function calls you don't wish

    to step into. You can repeat the last command by simply pressing enter. You can use the continue command to tell gdb to continue executing

    until the next breakpoint or it finishes the program.

    If you want to peek at variables, you can issue the print command on the

    variable. For example: print mystruct->data.

    You can also set variables using the set command. For example: setmystruct->data = 42.

    The ptype command can tell you what type a particular variable is.

    Debugging using gdb

  • 8/7/2019 Advanced_C

    116/117

    gg g g g

    The commands instruction tells gdb to set a particular number ofcommands and to report them to you. For example, commands 1 will

    allow you to enter in a variable number of other commands (one per

    line, end it with "end"), and will report those commands to you once

    breakpoint 1 is hit.

    The clear command tells gdb to clear a specified breakpoint. The list command can tell you where you are at in the particular code

    block.

    You can specify breakpoints not only with lines but with function

    names.

    For more information on other commands, you can issue the helpcommand inside gdb.

    Debugging using dbx

  • 8/7/2019 Advanced_C

    117/117

    gg g g dbx is a multi-threaded program debugger. This program is

    great for tracking down memory leaks. dbx is not found onlinux machines (it can be found on Solaris or other *NIXmachines).

    Run dbx with the executable like gdb. Now you can setarguments with runargs.

    After doing that, issue the check -memuse command. Thiswill check for memory use. If you want to also check foraccess violations, you can use the check -all command.

    Run the program using the run command. If you get anyaccess violations or memory leaks, dbx will report them to

    you.

    Run the help command if you need to understand othercommands or similar gdb commands.