This is an old revision of the document!
Macrou-ul DIE folosit în sursele din laborator e util pentru verificarea codului de eroare întors de un apel de sistem.
Exemplu de utilizare:
fd = open("some file", O_CREAT, 0644); DIE(fd < 0, "invalid file descriptor");
Macro-ul DIE este definit în fișierul util/utils.h
din arhiva laboratorului și arată în felul următor:
#define DIE(assertion, call_description) \
do { \
if (assertion) { \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
exit(EXIT_FAILURE); \
} \
} while(0)
Dacă verificarea specificată prin assertion
eșuează, se afișează detalii despre eroare și se iese imediat din program, deci nu se eliberează resursele.
O abordare mai profesionistă, dar un pic mai complexă, presupune folosirea intrucțiunii goto. Exemplu:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(void) { int fd1, fd2; fd1 = open("file1", O_CREAT | O_RDWR, 0644); if (fd1 < 0) { perror("open file1 failed"); goto exit_1; } fd2 = open("file2", O_CREAT | O_RDWR, 0644); if (fd2 < 0) { perror("open file2 failed"); goto exit_2; } /* ... rest of the code ...*/ return 0; exit_2: close(fd1); exit_1: return -1; }
Un macro DIE_CB, care primește și o funcție ce poate fi folosită pentru cleanup.
fd1 = open("some file", O_CREAT, 0644); DIE(fd1 < 0, "invalid file descriptor"); fd2 = open("other file", O_CREAT, 0644); /* Va apela close(fd1) */ DIE_CB(fd2 < 0, "invalid file descriptor", close, fd1);
Primește ca parametri extra: un numele unei funcții și lista de argumente ce trebuie pasată funcției.
#define DIE_CB(assertion, call_description, callback, ...) \
do { \
if (assertion) { \
callback(__VA_ARGS__); \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
exit(EXIT_FAILURE); \
} \
} while(0)
DIE_BLOCK rezolvă problema de a avea funcții pentru fiecare cleanup.
fd1 = open("some file", O_CREAT, 0644); DIE(fd1 < 0, "invalid file descriptor"); fd2 = open("other file", O_CREAT, 0644); /* Va apela close(fd1) */ DIE_BLOCK(fd2 < 0, "invalid file descriptor", close(fd1)); fd3 = open("another file", O_CREAT, 0644); DIE_BLOCK(fd3 < 0, "invalid file descriptor", { close(fd1); close(fd2); });
Primește ca parametri extra: un block de cod valid.
#define DIE_BLOCK(assertion, call_description, cleanup_block) \
do { \
if (assertion) { \
cleanup_block; \
fprintf(stderr, "(%s, %d): ", \
__FILE__, __LINE__); \
perror(call_description); \
exit(EXIT_FAILURE); \
} \
} while(0)
Pentru că aplicațiile din laborator urmăresc în primul rând formarea deprinderii de a verifica mereu codul de eroare întors de apelurile de sistem, puteți folosi macro-ul DIE în rezolvarea task-urilor din laborator.