2016-12-13 4 views
0

l'exemple de code est comme ceci:pourquoi fstream zéro errno dans la fonction destructor

void testFuncErrno() 
{ 
    fstream fstr; 
    fstr.exceptions(std::ifstream::failbit | std::ifstream::badbit); 
    try 
    { 
     fstr.open("/mnt/virtualfs/test.ss", ofstream::out); 
     fstr << "test" << endl; 
    } 
    catch(std::ifstream::failure e) 
    { 
     cout << "func catch errno is:" << errno << ":" << strerror(errno) << endl; 
     cout << "good?" << (fstr.good()?"yes":"no") << endl; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    try 
    { 
     errno = 0; 
     testFuncErrno(); 
     cout << "0 st errno is:" << errno << ":" << strerror(errno) << endl; 
    } 
    catch(std::ifstream::failure e) 
    { 
     cout << "catch errno is:" << errno << ":" << strerror(errno) << endl; 
    } 
    pause(); 
    return 0; 
} 

lorsque le disque est plein, je veux attraper le errno, mais il semble que le errno sera mis à zéro lorsque la fonction terminée. J'utilise ddd pour tracer le code source, et a trouvé quelques commentaires ci-dessous, mais de la description de errno:

errno est mis à zéro au démarrage du programme, et toute fonction de la bibliothèque standard C peut modifier sa valeur à certains valeur différente de zéro, généralement pour signaler des catégories d'erreurs spécifiques (aucune fonction de bibliothèque ne remet sa valeur à zéro une fois modifiée).

cela me fait un peu confuse, pourquoi la fermeture va mettre errno à zéro?

__basic_file<char>* 
    __basic_file<char>::close() 
    { 
    __basic_file* __ret = static_cast<__basic_file*>(NULL); 
    if (this->is_open()) 
     { 
    int __err = 0; 
    if (_M_cfile_created) 
     { 
     **// In general, no need to zero errno in advance if checking 
     // for error first. However, C89/C99 (at variance with IEEE 
     // 1003.1, f.i.) do not mandate that fclose must set errno 
     // upon error.** 
     errno = 0; 
     do 
      __err = fclose(_M_cfile); 
     while (__err && errno == EINTR); 
     } 
    _M_cfile = 0; 
    if (!__err) 
     __ret = this; 
     } 
    return __ret; 
    } 
+0

bien, je teste également la fonction de fstream :: close() dans un cas normal, et il ne réglez le errno à zéro. Mais je dois attraper cette errno dans mon programme pour envoyer l'erreur de manquer de l'espace disque. – aldam70

Répondre

0

Il est une bonne pratique de mettre errno à zéro avant d'appeler une fonction de bibliothèque connue pour définir errno, et vérifier errno seulement après que la fonction retourne une valeur indiquant l'échec. En effet, la valeur de errno peut être définie sur non nulle par un appel de fonction de bibliothèque standard C, qu'il y ait ou non une erreur, à condition que l'utilisation de errno ne soit pas documentée dans la description de la fonction. Par conséquent, si vous initialisez errno uniquement au début du programme, il n'y a aucune garantie que la valeur de l'erreur est définie par l'appel de la fonction.

La définition d'une erreur à 0 juste avant d'appeler fclose() confirme que la valeur de cette erreur est définie par fclose() et aucune autre fonction.

Vous trouverez ci-dessous la discussion d'utilisation: https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=6619179

+0

Le mettre à zéro est une mauvaise pratique. Ce qui est une bonne pratique, ce n'est pas de tester 'errno' sauf si vous * savez * qu'il y a eu une erreur immédiatement antérieure, qui est invariable signalée par l'appel système concerné retournant -1. – EJP