errno



  • Hallo,

    hab mal eine Frage zu errno. Hier erstmal mein Code.

    [cpp]
    errno = 0;
    char *pointer = malloc(sizeof(char *));
    if(pointer == NULL){
        perror("malloc failed");
    return -1;
    }
    [/cpp]
    

    Meine Frage: Warum muss man errno vor der Nutzung von z.B. hier perror() auf 0 setzten. In errno steht doch immer nur ein Wert und in diesem Fall hier kann, falls malloc fehlschleagt errno ENOMEM sein und diese Fehlermeldung wird dann ausgegeben. Wieso soll man also vor Systemaufrufen/Bibliotheksfunktionen immer auf 0 setzten? Oder können in errno mehrere Fehler gespeichert werden?
    Danke im voraus.



  • Du musst errno nicht auf 0 setzen.



  • Sollte man das? Ist mir neu. Ich vermute(!), das kommt daher, dass die Systemaufrufe nicht garantiert errno auf 0 setzen, wenn sie erfolgreich sind, so dass folgendes Muster schief geht:

    systemaufruf();
    if (errno != 0) {
      /* oh oh! */
    }
    

    Das macht man aber sowieso nicht durch Abfragen von errno, sondern indem man den Rückgabewert des Systemaufrufs auswertet, von daher versteh ich den Sinn dieses Tipps nicht wirklich.



  • Mal als Beispiel strtoul()

    Retval schrieb:

    On success, the function returns the converted integral number as a long int value.
    If no valid conversion could be performed, a zero value is returned.
    If the correct value is out of the range of representable values, ULONG_MAX is returned, an the global variable errno is set to ERANGE. Notice that ULONG_MAX is also a valid in-bound return value (in this case errno is not modified by strtoul).

    Wenn man zwischen zwei strtoul() Aufrufen errno nicht auf 0 setzt, kann das schief gehen.

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    int main()
    {
      unsigned long l;
    
      errno = 0;
      l = strtoul("4294967295",NULL,10);
      printf("%d, %lu\n", errno, l); 
      l = strtoul("4294967296",NULL,10);
      printf("%d, %lu\n", errno, l);
      l = strtoul("4294967295",NULL,10);
      printf("%d, %lu\n", errno, l);
    
      return 0;
    }
    

    Ausgabe schrieb:

    0, 4294967295
    34, 4294967295
    34, 4294967295



  • Also muss ich in meinem Fall errno nicht auf 0 setzten, nur wenn ich errno in einer Fehlerabfrage habe, dann muss man errno vorher auf 0 setzten. oder kann es sein das perror nicht nur den aktuellen wert von errno ausgibt, sondern auch alle älteren werte.



  • Also muss ich in meinem Fall errno nicht auf 0 setzten, nur wenn ich errno in einer Fehlerabfrage habe, dann muss man errno vorher auf 0 setzten. oder kann es sein das perror nicht nur den aktuellen wert von errno ausgibt, sondern auch alle älteren werte.
    ???



  • Nein, nur den aktuellen.



  • Ok.
    Jetzt noch eine Frage. Setzt malloc, falls es fehlschlägt, immer errno auf irgendeinen Wert? Weil falls nicht, dann wäre das im diesem Fall problematisch. Denn dann würde malloc z.b. fehlschlagen und danach würde perror einen falschen Wert von errno ausgeben.
    p.s.: Wäre aber auch nicht ganz sinnvoll,wenn man errno vorher auf 0 setzt, dann würde perror auch nicht den Fehler ausgeben.



  • val = atoi( str );
    if( errno == ERANGE || errno == EINVAL )
    {
    	_set_errno( 0 ); // errno zurücksetzen
    	...
    }
    

    Falls beim 1. Aufruf errno gesetzt wird und du errno nicht zurücksetzt hat errno bei einem 2. Aufruf (mit einem gültigen Wert) immer noch den Wert vom 1. Aufruf.



  • Danke für die Antwort. Aber das war nicht die Antwort auf meine Frage. Das, was du mir erklärt hast, weis ich schon. Mir geht es darum, ob die Speicherbelegung mit malloc fehlschlagen kann(aus welchen Grund auch immer) und errno nicht gesetzt wird. Sodass dann bei der Fehlerausgabe ein falscher Wert in errno steht.



  • Ja, das kann sein. Der Standard (zumindest der letzte C99-Draft, den ich hier habe) sagt bei malloc nichts über errno, er sagt nur ganz allgemein, dass jede Library-Funktion errno verändern kann.


Anmelden zum Antworten