This is an old revision of the document!


Macro-ul DIE

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)

Dezavantaje

Dacă verificarea specificată prin assertion eșuează, se afișează detalii despre eroare și se iese imediat din program, deci nu se eliberează resursele.

Alternativă

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;
 
}

Altă opțiune

Un macro DIE_CB, care primește și o funcție ce poate fi folosită pentru cleanup, rezolvând astfel dezavantajul de a nu elibera resursele.

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)

Altă opțiune

DIE_BLOCK rezolvă problema de a avea funcții pentru fiecare cleanup și dezavantajul de a nu elibera resursele.

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)

Concluzie

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.

so/laboratoare/resurse/die.1427021480.txt.gz · Last modified: 2015/03/22 12:51 by razvan.deaconescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0