2009-10-03 11 views

Odpowiedz

23

Funkcje Microsoft *_s są nieprzenośne, ja zwykle używam równoważnych funkcji C89/C99 i wyłączam ostrzeżenia o wycofaniu (#define _CRT_SECURE_NO_DEPRECATE).

Jeśli upierasz, można użyć funkcję adaptera (niekoniecznie makro!), Że delegaci fopen() na platformach, które nie mają fopen_s(), ale trzeba być ostrożnym do mapowania wartości errno_t kodu powrotu z errno.

errno_t fopen_s(FILE **f, const char *name, const char *mode) { 
    errno_t ret = 0; 
    assert(f); 
    *f = fopen(name, mode); 
    /* Can't be sure about 1-to-1 mapping of errno and MS' errno_t */ 
    if (!*f) 
     ret = errno; 
    return ret; 
} 

Jednak nie widzę jak fopen_s() jest bardziej bezpieczny niż fopen(), więc zazwyczaj przejść do przenoszenia.

+5

Microsoft LOVES tworzy własną wersję. Zastanawiam się, dlaczego ... – LiraNuna

+9

Zabawne jest to, że są teraz częścią C11 (aczkolwiek w opcjonalnym Załączniku K). – rubenvb

+0

Znacznie lepiej niż moje (teraz poprzednie, nie, że już tego potrzebuję) czysto makro.Twoje podejście do funkcji częściowo powiela zachowanie fopen_s po niepowodzeniu, zwracając errno (= EINVAL, tj. 22, fwiw). Można również wygenerować wyjątek * nieprawidłowego parametru *, aby jeszcze lepiej dopasować zachowanie fopen_s. – riderBill

4

w C/C++ kod,

#ifdef __unix 
#define fopen_s(pFile,filename,mode) ((*(pFile))=fopen((filename),(mode)))==NULL 
#endif 

W Makefile

CFLAGS += -D'fopen_s(pFile,filename,mode)=((*(pFile))=fopen((filename),(mode)))==NULL' 

Uwaga że w przypadku powodzenia return 0 fopen_s podczas fopen zwraca niezerowy wskaźnik pliku. Dlatego konieczne jest dodanie "== null" do końca makro, np:

if (fopen_s(&pFile,filename,"r")) perror("cannot open file"); 
1

Wiele bezpiecznych funkcji firmy Microsoft znajduje się w załączniku K do standardu C11, ale nie jest powszechnie obsługiwane, więc przenośność nadal stanowi problem. W niektórych zastosowaniach istnieje potrzeba poprawy bezpieczeństwa; może wsparcie poprawi się w przyszłości.

I przeszłość, zrobiłem to tak:

#define fopen_s(fp, fmt, mode)   *(fp)=fopen((fmt), (mode)) 

Makro jest proste i prosto do przodu, wystarczająco dobry na coś szybkiego i brudne, ale nie zapewnia zachowania wyjątkiem fopen_s i nie zapewni bezpieczeństwa prawdziwej funkcji fopen_s.

@ Podejście funkcji ALE B powyżej częściowo odtwarza prawidłowe zachowanie po awarii; zwraca errno (= EINVAL). Jego podejście można jeszcze bardziej rozszerzyć, generując wyjąteko nieprawidłowym parametrze, aby w pełni odtworzyć zachowanie fopen_s.