Recita'on*By*yzhuang,*sseshadr**Agenda*• Debugging*prac'ces*– GDB*– Valgrind*– Strace*• Errors*and*Wrappers*– System*call*return*values*and*wrappers*– Unini'aliza'on*– malloc() related*bugs*• System*IO*Debugging*Prac'ces*General*Debugging*• prinFs*are*a*good*start,*but*won’t*solve*ever ything*• Remember*prinFs*CHANGE*your*code*– And*how*it’s*compiled*– And*how*it*runs*• Especially*for*races*• A*lot*of*the*debugging*tools*should*be*used*with*the*–g*compiler*flag*GDB*• From*bomblab*/*buflab*• You*WILL*need*it*for*malloc*• Demo?*Valgrind*• Memory*related*i ssu es*• Lots*of*op'ons*• man valgrind • valgrind --leak-check=full ./a.out • Demo?*strace*• From*the*man*page*– “In*the*simplest*case*strace*runs*the*specified*command*un'l*it*exits.**It#intercepts#and#records#the#system#calls#which#are#called#by#a#process#and#the#signals##which#are#received#by#a#process.**The*name*of*each*system*call,*its*arguments*and*its*return*value*are*printed*on*standard*error*or*to*the*file*specified*with*the*Yo*op'on.”*• Cool*for*debugging!*Errors*and*Wrappers*System*Call*Error*Handli ng*• Always*handle*errors*for*every*system*call*– #include*<errno.h>*– Failed*system*calls*almost*always*return*Y1*– Global*integer*error*number:***errno*– Geang*error*descrip'on:**strerror(errno)*• We*deduct*style*points*for*not*handling*system*call*errors*Wrappers*• If*a*system*call*is*frequentl y*used,*create*a*wrapper*fo r*it.*For*example:**pid_t Fork(void){ pid_t pid; if ( (pid = fork() ) < 0 ){ //error handling } return pid; } • Proclab:**always*handle*errors*– You*can*choose*whether*to*use*wrappers*malloc*• #include*<stdlib.h>*• void**malloc(size_t*size);*• Allocates*size*bytes*of*memory*• A*pointer*is*returned*• Returned*memory*unini8alized!!#p=(struct cacheline*) malloc( sizeof(cacheline) ); P->valid = ???? – Cachelab:**using*unini'alized*valid*bit*(very*bad)!*calloc*• With*malloc*– Either*ini'alize*– Or*use*calloc*• void***calloc*(*size_t*num,*size_t*size*);*– Allocate*num***size*bytes*of*memory*– Ini'alized*to*0*• Caveat:**what*if*num***size*causes*an*overflow?**Check*before*calling*calloc.*free*• Free*memory*allocated*by*malloc/calloc*• Common*mistakes:*– Freeing*memory*already*freed*– Freeing*memory*not*allocated*– Wri'ng*to*memory*already*freed*– IndexYoutYofYbound*accesses*of*allocated*array*– Not*freeing*allocated*memory*I/O*System*I/O*Basics*• Four*basi c*op era'ons:*– open – close – read – write • What’s*a*file*descriptor?*– Returned*by*open.*– int fd = open(“/path/to/file”, O_RDONLY); • fd*is*some*posi've*value*or*Y1*to*denote*error*System*I/O*Basics*• Every#process*starts*with*3*open*file*descriptors*– 0 *Y *STDIN*– 1 *Y *STDOUT*– 2 *Y *STDERR*• Can*I*close*these*file*descriptors?*– Yes!*– But*you*shouldn’t…*this*next*example*is*just*for*illustra've*purposes*Sample*Code*#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char ** argv){ int fd = atoi(argv[1]); argc = argc; /* Keep GCC Happy */ fprintf(stdout, "STDOUT:close(%d) = %d\n",fd,close(fd)); fprintf(stderr, "ERROR:close(%d) = %d\n",fd,close(fd)); return 1; } What*are*the*outpu ts*when*run *with./a.out 0 ,* ./a.out 1 ,*and *./a.out 2*?*Sample*Code*#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char ** argv){ int fd = atoi(argv[1]); argc = argc; /* Keep GCC Happy */ fprintf(stdout, "STDOUT:close(%d) = %d\n",fd,close(fd)); fprintf(stderr, "STDERR:close(%d) = %d\n",fd,close(fd)); return 1; } >> ./a.out 0 STDOUT:close(0) = 0 STDERR:close(0) = -1 >> ./a.out 1 STDERR:close(1) = -1 >> ./a.out 2 STDOUT:close(2) = 0 Why*Y1*on*the*second*'me??*Why*no*STDOUT*output?*And*why*Y1*for*close*return*value?*Why*no*STDERR*output?*And*why*0*for*close*return*value*this* 'me?*Some*Real*Stuff*From*Lecture:*Some*Real*Stuff*From*Lecture:*CALL#TO#fork()Some*Real*Stuff*From*Lecture:*Dup*• What*is*file*redirec'on?*– Redirec'on*vs.*Pipes*• Redirec'on*has*one*“input”*of*a*file,*pipes*can*be*between*tasks*• Ex:*cat < filename • Ex:*find . | cat – What*is*dup2?*• It*switches*which*file*a*file*descriptor*is*poin'ng*to !*– What*is*dup?*• It*ini'alizes*anoth er*file*descriptor*to*point*to*an*already*exis'ng*file!*Some*Real*Stuff*From*Lecture:*Some*Real*Stuff*From*Lecture:*CALL#TO#dup2(4,1)Dup*From*Lecture*Dup*• So*what*is*dup,*and*what*is*dup2?*– int fd1 = open(…); int fd2 = dup(fd1); – int fd1 = open(…); int fd2; dup2(fd1, fd2); • Are*these*the*same??*– NO!*– The*first*is*OK,*the*second*uses*an*unini'alized*variable!*Remember,*it’s*not**dup2(fd1, &fd2);File*wri'ng*example*• Ques'ons*– What*are*all*of*the*possible*contents*of*the*file*aqer*running*this*code??*– What*is*wrong*with*th e*style*of*this*code?*– How*would*you*close*these*file*descriptors?*#include <stdio.h> #include <unistd.h> int main() { int fd1, fd2, fd3, parent = 0; char *fname = "filename"; fd1 = open(fname, O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR); write(fd1, "A", 1); fd3 = open(fname, O_APPEND|O_WRONLY, 0); write(fd3, "BBB", 3); if((parent = fork())) fd2 = dup(fd1); else fd2 = fd3; write(fd2, "C", 1); write(fd3, "D", 1); if(parent) waitpid(-1, NULL, 0); return 0; }File*wri'ng*example*• Answers*– Possible*outputs:*• ACBBDCD*• ACBBCDD*– What*is*wrong*with*the*style*of*this*code?*• Didn’t*check*error*codes,*didn’t*close*anything,*no*comments .**– How*would*you*close*these*file*descriptors?*• fd2*some'mes*needs*close()’d,*some'mes*doesn’t!*• So:*don’t*do*both*fd2 = fd3;*and*fd2 = dup(f1);Prac'ce!!*• Tons*of*prac'ce*available*in*past*exam*#2’s*• Very*likely*to*be*an*I/O*ques'on*on*the*nex
View Full Document