代写 C data structure shell More on C

More on C
• Command line arguments
• Stream IO
• Reporting errors found by many c library routines • Free
1

Command Line Arguments
• Recall bash will send arguments to commands
–e.g. grep –iw horse carol.txt
–the bash shell sends to the grep command
the arguments ‘-iw’ ‘horse’ ‘carol.txt’
• The shell will also send arguments to your C programs
• But how do we access these arguments?
2

Accessing command line arguments
• Command-line arguments to a program are given to the program as an array of (pointers to) strings
char *argv[]
• No. of arguments (= size of this array) provided separately int argc
• Accessed within the program as int main(int argc, char *argv[])
program name
first argument last argument
argv[0]
argv[1]

argv[ argc- 1]
3

Example 1
argv[0] is always the name of the executable
argv[1] … argv[(argc-1)] are the command line arguments, in order
4

Example 2
#include
// Show all the command line arguments by walking the array // argv of strings using pointer arithmetic. Notice that // argc and argv are changed in the process.
int main( int argc, char**argv) {
printf(“>> Total number of arguments is %d\n”, argc);
while (argc–)
{
printf(“Dereferenced ‘argv’, i.e., argv[0] is %s\n”, *argv++);
}
return 0; }
rock:examples kobus$ ./a.out a b ‘c d’
>> Total number of arguments is 4 Dereferenced ‘argv’, i.e., argv[0] is ./a.out Dereferenced ‘argv’, i.e., argv[0] is a Dereferenced ‘argv’, i.e., argv[0] is b Dereferenced ‘argv’, i.e., argv[0] is c d
6

Streams
• A stream is any source of input or any destination for output – conceptually, just a sequence of bytes
– accessed through a file pointer, which has type
FILE *
however, not all streams are associated with files
– three standard predefined streams: stdin, stdout, stderr
(you do not need to open or close these)
7

Streams
network
keyboard monitor
hard disk
program (i.e., pipe)
program
stdin
stdout stderr
8

Streams
network
keyboard monitor
hard disk
program (i.e., pipe)
program
stdin
stdout stderr
streams provide an abstraction of a byte sequence for I/O
9

Typical structure of I/O operations
A program’s I/O operations usually have the following structure: 1. Open a file
2. Perform I/O
3. Close the file
fopen
fprintf, fscanf, fread, fwrite, fgets
fclose
Usually you want the code block that opens the stream to also close it.
10

Opening a file
FILE * fopen(char *filename, char *mode)
name of file to open
“r”
read
“w”
write (file need not exist)
“a”
append (file need not exist)
“r+ ”
read and write, starting at the beginning
“w+ ”
read and write; truncate file if it exists
“a+ ”
read and write; append if file exists
file pointer for the stream, if fopen succeeds;
NULL otherwise
11

Closing a file
int fclose(FILE *fp)
file pointer for stream to be closed
return value:
0 if the file was closed
successfully; EOF otherwise
12

Code structure
FILE *fp;

fp = fopen(filename, “r”); // or whatever mode is appropriate if (fp == NULL) {
… give error message and exit … }
… read and process file … status = fclose(fp);
if (status == EOF) {
… give error message… }
13

Reading and writing • fprintf,fscanf
– similar to printf and scanf, with additional FILE * argument
• fread(ptr,sz,num,fp)
– reads num elements, each of size sz, from stream fp and stores them at ptr
– does not distinguish between end-of-file and error • usefeof()andferror()
• fwrite(ptr,sz,num,fp)
– writes num elements, of size sz, from ptr into stream fp
• returnvalues:
– no. of items successfully read/written (not no. of bytes)
14

Example: fread
open the file for reading
check for EOF
(fread does not distinguish
between EOF and error)
read from the file (as much as will fit in the buffer)
close the file when done (should check for errors)
15

Example: fscanf
16

fscanf
17

Errors
• fopen() can fail for many different reasons
18

Giving sensible error messages: perror
19

perror
20

perror
21

More on perror
• Perror constructs error messages from an error code stored in the global variable “errno” (defined in errno.h)
• Cooperating library routines set the global variable “errno” when they encounter error
– They do not touch it when they succeed
– The next error will overwrite the previous one
– You can overwrite errno if you like
– Consequence: What perror() reports can be stale and/or confusing
– Best to consult errno (perhaps via perror()) immediately after a system call returns something that “man” tells you leads to errno being set.
22

Motivation
• Dynamically allocated memory should be freed when no longer needed
– The C runtime system does not automatically reclaim memory
– memory leaks increase the program’s memory footprint • thiscanleadtoslowperformance,programcrashes
• This needs to be done with care:
– freeing what you should not leads to program errors
– not freeing when you should leads to memory leaks
• EG, too-passive freeing can miss memory allocated “behind the scenes”, e.g., through strdup().
23

Issues
• Understanding when dynamic memory allocation happens – explicit (by the programmer)
– implicit (by library routines)
• Through the course of the program:
– identifying when memory is no longer needed
– being aware of multiple pointers to a block of memory
• Identifying and fixing memory leaks
24

Understanding dynamic memory allocation
• Dynamicallocationcanbeexplicitorimplicit
– explicit: when the programmer invokes malloc, calloc, etc.
– implicit: when the memory allocation happens “behind the scenes” in a library routine
• getline
• strdup
• GNUextensiontoscanf • fopen
•…
In general, if memory appears “by magic” at runtime, chances are it’s being allocated implicitly.
25

Freeing up memory

Use free(p) when a memory block is no longer needed
– p is a pointer to a block of memory previously allocated through malloc or calloc
• Pitfalls:
– accessing a previously-
freed block is an error
– freeing a block of memory twice is an error
watch out for multiple ways to reach a memory block
malloc’d memory block
pointer
26

Freeing up memory
• Generalapproach:
– free up memory “hanging off” a block of memory
– copy any pointers you need to traverse the rest of the data structure – then free the block itself
1 deallocate
memory “hanging off” this node
23
grab this pointer free this block
27

Finding memory leaks 1
use valgrind to determine whether the program has memory leaks
28

Finding memory leaks 2
indicates where the lost memory was allocated
29

Finding memory leaks 2
forgot to fclose() after reading the file!
30

After fclose-ing the input stream
less leakage than before, but still quite a bit
need to free the linked list of states
31

Freeing up a linked list 1
naïve code to free the nodes in a linked list
32

Freeing up a linked list 1
naïve code to free the nodes in a linked list
33

Freeing up a linked list 2
stateList st0 st1
34

Freeing up a linked list 3
35

Freeing up a linked list 3
• no memory errors
• less memory being leaked • but some leakage persists!
• reason: structures “hanging off” states not being freed
36

Freeing up a linked list 3
• no memory errors
• less memory being leaked • but some leakage persists!
• reason: structures “hanging off” states not being freed
// a DFA state
typedef struct vertex {
char *name;
struct edge *transitions; bool isFinal;
struct vertex *next;
} state;
// a transition between states typedef struct edge {
char ch;
struct vertex *from, *to; struct edge *next;
} edge;
37

Freeing up a linked list 4
Solution: free up the edges “hanging off” each state before freeing that state
38

Freeing up a linked list 4
a lot better!
but some leakage still left!
39

Freeing up a linked list 4
// a DFA state
typedef struct vertex {
char *name;
struct edge *transitions; bool isFinal;
struct vertex *next;
} state;
40

Freeing up a linked list 5
41

Freeing up a linked list 5
42

Summary
• Should free up dynamically allocated memory when done – Use valgrind to identify memory leak sources!
• Needs to be done carefully
– freeing up “live” memory will result in program errors
• Pay attention to implicitly-allocated memory, e.g.: – file pointers
– strings allocated through strdup() – lines allocated using getline()
• When freeing up a struct, first free up any unused memory “hanging off” the struct
43

Things to Avoid
• Don’t use memory that has been freed.
• Don’t try to free memory more than once.
• Only send to free a pointer to the START of memory that has been dynamically allocated (malloc, calloc, getline, etc.)
44

Suggestions
• Initialize pointers to NULL – It is OK to free(NULL)
• Testincrementally,andusevalgrindasapplicable
• Try to allocate and deallocate in the same code block
– Exceptions
• When the point of the function is to build something (e.g., add a note to list)
• Draw your data structures and do not forget design
• Be careful
– Your code does exactly what you tell it to!
45