
C Programming Lab: Assessment, Important Topics, and Exercises
Explore C programming concepts with a focus on memory management and common library functions. Assess your readiness through exercises and learn key topics like pointers, memory management, and common library functions. Discover errors in code and how to handle memory allocation efficiently for a successful C programming experience.
Download Presentation

Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.
E N D
Presentation Transcript
15-213 RECITATION CACHE LAB AND C Aishwarya PremRenu 16 Feb 2015
Agenda o Buffer lab Due TOMORROW! oCache lab Out TOMORROW! Due 26thFeb oC Assessment o Using the C Standard Library oCompilation (gccand make) o Debugging Tips (Yes, you can still use GDB. ) oVersion Control o Style o Demo
C Assessment oCache Lab = First Programming in C Lab oSteps to see if you re ready: oCan you solve all of these upcoming C-exercises effortlessly? oThese problems test fundamental C-concepts. oIf not, please come to the C-bootcamp oDATE, TIME, LOCATION: TBA oYou need this for the rest of the course. So, if in doubt, COME TO THE BOOTCAMP, and get all your doubts cleared!
Important C Topics o Types: Pointers/Structs o Memory Management: Malloc/Free, Valgrind o Common library functions: string.h, stdlib.h, stdio.h o Grab-bag: macros, typedefs, function-pointers, header-guards
Exercise #1 Spot the errors! int main() { int* a = malloc(100*sizeof(int)); for (int i=0; i<100; i++) { if (a[i] == 0) a[i]=i; else a[i]=0; } free(a); return 0; }
Exercise #1 Malloc does not initialize memory! So you get junk data, and the behavior of main is undefined. int main() { int* a = malloc(100*sizeof(int)); /* Q.3 Is anything missing here? */ for (int i=0; i<100; i++) { if (a[i] == 0) a[i]=i; else a[i]=0; } int b = sizeof(a); int c = (a == &a[0]); free(a); return 0; } Q.1 What can you use instead of malloc, so you can be sure of the contents? Q.2 What are the values of b and c? Q.4 What does free(a) do?
Exercise #1 int main() { int* a = malloc(100*sizeof(int)); if(a == NULL) { callerror(); //Define your own function return; } for (int i=0; i<100; i++) { if (a[i] == 0) a[i]=i; else a[i]=0; } free(a); int b = sizeof(a); int c = (a == &a[0]); return 0; } Malloc may return NULL! In that case, you would get a dreaded Segmentation fault when you try to dereference. And Nope, you do not want that happening. // b = 8 (for 64-bit systems) // c = 1
Exercise #2 Q.1 What are the values of c and d? #define SUM(a,b) a+b int sum(int a, int b) { return a+b; } int main { int c = SUM(2,3)*4; int d = sum(2,3)*4; return 1; }
Exercise #3 Safe or not? int * funfun(int * allocate) { allocate = malloc(sizeof(int)); int a = 3; return &a; } int main { } int * ptr1; int * ptr2 = funfun(ptr1); printf( %p %p , ptr1, ptr2); return 1;
Exercise #3 Safe or not? int * funfun(int * allocate) { allocate = malloc(sizeof(int)); int a = 3; return &a; } Function returning address of local variable! Not allowed that was allocated on the stack and is not safe to access after you return from funfun! int main { } int * ptr1; int * ptr2 = funfun(ptr1); printf( %p %p , ptr1, ptr2); return 1; Note: Printing pointer values
Exercise #4 struct node { int a; struct node* next; }; typedef struct node * nodeptr; Spot the errors! int main() { } nodeptr ** data = (nodeptr **)malloc(4*sizeof(nodeptr *)); for( int i = 0; i<4; i++) { data[i] = (nodeptr *)malloc(3*sizeof(nodeptr)); } for( int j = 0; j<3; j++) { data[0][j]->a = 213; }
Exercise #4 struct node { int a; struct node* next; }; typedef struct node * nodeptr; data[i] has been allocated to be of type nodeptr *, However, each of these nodeptr in the heap do not point to anything yet, and are uninitialized! Hence, when you dereference data[0][j], you get a Segmentation Fault. int main() { } nodeptr ** data = (nodeptr **)malloc(4*sizeof(nodeptr *)); for( int i = 0; i<4; i++) { data[i] = (nodeptr *)malloc(3*sizeof(nodeptr)); } for( int j = 0; j<3; j++) { data[0][j] = malloc(sizeof(struct node)); data[0][j]->a = 213; } /* Free everything you malloc! */ Q. Now, are all accesses safe?
Exercise #4 struct node { int a; struct node* next; }; typedef struct node * nodeptr; data[i] has been allocated to be of type nodeptr *, However, each of these nodeptr in the heap do not point to anything yet, and are uninitialized! Hence, when you dereference data[0][j], you get a Segmentation Fault. NO! Check if what malloc returned is non- NULL before you dereference! int main() { } nodeptr ** data = (nodeptr **)malloc(4*sizeof(nodeptr *)); for( int i = 0; i<4; i++) { data[i] = (nodeptr *)malloc(3*sizeof(nodeptr)); } for( int j = 0; j<3; j++) { data[0][j] = malloc(sizeof(struct node)); data[0][j]->a = 213; } /* Free everything you malloc! */
Use the C Standard Library oPlease Use it! oDon t write code that s already been written! o Your work might have a bug or lack features o You spend time writing code that may be inefficient compared to an existing solution. oAll C Standard Library functions are documented. oSome of the commonly used ones are: o stdlib.h: malloc, calloc, free, exit, atoi, abs, etc o string.h: strlen, strcpy, strcmp, strstr, memcpy, memset, etc o stdio.h: printf, scanf, sscanf, etc oUse the UNIX man command to look up usage / online references.
Example: getopt int main(int argc, char** argv) { int opt, x; /* looping over arguments */ while(-1 != (opt = getopt(argc, argv, x:"))) { switch(opt) { case 'x': x = atoi(optarg); break; default: printf( wrong argument\n"); break; } } } o getopt is used to break up (parse) options in command lines for easy parsing by shell procedures, and to check for legal options. (From the man pages! See, it s really helpful!) o Use it to parse command line arguments and don t write your own parser! o Colon in x: indicates that it is a required argument o optarg is set to value of option argument o Returns -1 when no more args are present o Useful for Cache lab!
Write Robust Code We are writing code for the real world: errors will happen! oSystem calls may fail oUser may enter invalid arguments oConnections may die --- Experience with this in Proxylab! o but your code should NOT crash! Handle errors gracefully oIndicate when errors happen oThey may be recoverable, you may have to terminate oRemember to free any resources in use oElse, suffer the wrath of a thousand unicorns o and our sadistic style-grading.
Solution 1 : Use CS:APP Wrappers o http://csapp.cs.cmu.edu/public/1e/ics/code/src/csapp.c o It Has wrapper methods for all core system calls o Explicitly checks for return values and then calls unix_error if something went wrong void *Malloc(size_t size) { void *p; if ((p = malloc(size)) == NULL) unix_error("Malloc error"); return p; } o Copy/paste required wrappers in source code, since we will accept only single files in earlier labs. o Definitely include this file in your proxy lab submission!
Solution 2: Write your own checks o Example: file IO functions o Error-codes: o fopen:return NULL o fopen:open a given file in a given mode (read/write/etc) o fclose:close file associated with given stream o fscanf:read data from the stream, store according to parameter format o fclose: EOF indicated o fscanf:return fewer matched arguments, set error indicator FILE *pfile; if (!(pfile = fopen( myfile.txt , r ))) { printf( Could not find file. Opening default! ); pfile = fopen( default.txt , r ); } // file pointer o May be useful for Cache lab!
Compilation: Using gcc o Used to compile C/C++ projects: o List the files that will be compiled to form an executable o Specify options via flags o Use man gcc for more details o Important Flags: o -g: produce debug information (important; used by gdb/gdbtui/valgrind) o -Werror: treat all warnings as errors (this is our default) o -Wall/-Wextra: enable all construction warnings o -pedantic: indicate all mandatory diagnostics listed in C-standard o -O1/-O2: optimization levels o -o <filename>: name output binary file filename o Example: o gcc -g -Werror -Wall -Wextra -pedantic foo.c bar.c -o baz
Compilation: make oEasy way to automate bug shell command with lots of flags and files oMakefiles allow you to use a single operation to compile different files together oEfficient, because it only recompiles updated files oLab handouts come with a Makefile: Don t change them omake reads Makefile and compiles your project oSee http://www.andrew.cmu.edu/course/15-123- kesden/index/lecture_index.html for more details on how to make a Makefile
Debugging: gdbtui o Allows you to see source o Compile with g debug flag o Example: gcc g m32 myprog.c o myprog o Run using gdbtui myprog o layout src/asm/regs/split To display the source / assembly / registers / source & assembly layout o focus src/asm/regs Make the source / assembly / registers window active for scrolling
Debugging: valgrind o Use it to Find and eliminate memory errors, detect memory leaks o Common errors you can fix: o Illegal read/write errors o Use of uninitialized values o Illegal frees o Double frees o Overlapping source/destination addresses o Use gcc with g to get line number of leaks o Use valgrind --leak-check=full for thoroughness
Debugging: Small tip #ifdef DEBUG # define dbg_printf(...) printf(__VA_ARGS__) #else # define dbg_printf(...) #endif Use this to easily wither print or not print without having to comment out print statements each time!
Version Control o You should use it. Now. o Avoid suffering during large labs (malloc, proxy) o Basic ideas: o o o o Complete record of everything that happened in your code repository Ability to create branches to test new components of code Ease in sharing code with others Well, outside of 213 of course
Version Control Basics git init: Create a new repository Indicated by .git file o o o git status: Show working tree-status Untracked files, staged files o o o Warning git add <file_name> Stage a file to be committed (does not perform the commit) git add . stages all files in current directory o Be cautious when rewinding commits!!! Follow online usage instructions carefully! Use Stack Overflow, http://try.github.io, man pages o o git commit Make a commit from all the stage files git commit -m Commit message o o o
Style o Good documentation o Header comments, large blocks, tricky bits o Check error/failure conditions Must program robustly o 80 chars per line: Use grep '.\{80,\}' filename to find lines more than 80 chars o No memory or file descriptor leaks o Use interfaces for data structures (Don t repeat code) o Modularity of code o No magic numbers o Use #define o Consistency and whitespace o http://cs.cmu.edu/~213/codeStyle.html
Notes oGo to the C Boot Camp if you have any doubts! oC Boot Camp: o Time: TBD o Date: TBD o Location: TBD oWe are style grading from Cache lab onwards!
Acknowledgements oDerived from recitation slides by Arjun Hans, Jack Biggs oftp://ftp.gnu.org/old-gnu/Manuals/gdb/html_chapter/gdb_19.html ohttp://csapp.cs.cmu.edu/ oxkcd