Birgt das Gefahren?



  • soweit ich weiß, ist die einzig sichere form, hier va_list und freunde zu verwenden.

    void PrintStrs (int n, char const* str, ...)
    {
       va_list args;
       va_start (args, str);
    
       char const* next = str;
       for (int i = 0; i < n; ++i)
       {
          cout << next << endl;
          next = va_arg(args, char const*);
       }
    
       va_end (args);
    }
    

    ob das intern ähnlich wie du arbeitest, ist nicht spezifiziert (wozu auch?)

    /edit: jetzt hätte ich fast vergessen, zu erwähnen, dass es auch mit va_lists nicht unbedingt sicher wird.

    printStrs(3, "eins, zwei, drei", 4, "... ups");
    


  • Also ich weiss ja nicht, wie ihr das seht, aber sollte man nicht eher auf variable Listen verzicheten und eher auf vectore usw. setzen?

    Das geht ja relativ einfach und ist auch sicherer.



  • Ich meine, ist es zumindest so sicher wie printf()? Der Kern meiner Frage war eigentlich, ob die Methode auf die Variablen Argumente zuzugreifen sicher ist, oder ob Gefahr besteht, auf eine verbotene Speicheradresse zuzugreifen.
    Ich kann mir eben die offizielle Methode schlecht merken.



  • deine methode funktioniert nur dann sicher, wenn

    p += sizeof(char);
    

    auch tatsächlich auf das nächste funktionsargument zeigt.

    übrigens ist das eine sehr hässliche art und weise, um p++ zu schreiben. du inkrementierst den zeiger um eins, er zeigt aber dann auf eine adresse um sizeof(char*) weiter vorne (also idR um 4 bytes weiter).

    also: nein, nein, nein.



  • Stefan schrieb:

    Ich meine, ist es zumindest so sicher wie printf()? ...

    Da Du mindestens eine Fehlerquelle mehr hast als printf (s.a. Konrads Post), KANN es nicht "so sicher wie printf" (das übrigens auch sehr unsicher ist) sein ... schon gar nicht "mindestens".

    Stefan schrieb:

    ...Der Kern meiner Frage war eigentlich, ob die Methode auf die Variablen Argumente zuzugreifen sicher ist, oder ob Gefahr besteht, auf eine verbotene Speicheradresse zuzugreifen....

    Definitiv letzteres.
    Nochmal: warum übergibst Du nicht einfach einen vector (bzw. eine Referenz darauf) ?
    Funktioniert auch nicht anders, ist aber sicher in all den o.g. und weiteren Belangen.
    Schonmal nachgedacht, was passiert, wenn der Aufrufer Folgendes macht:

    myClass peng;
    PrintStrs(2, "Hallo", &peng);
    

    ?
    Bedenke bitte, dass (zumindest in C++) ein Design nur dann als "sicher" gilt, wenn der Benutzer keine Möglichkeit hat, für ihn unerwartetes Verhalten zu produzieren. ... und zwar nicht nur derjenige, der gerade gestern die Funktion selbst geschrieben hat, sondern auch wildfremde.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Stefan schrieb:

    Ich meine, ist es zumindest so sicher wie printf()? ...

    Da Du mindestens eine Fehlerquelle mehr hast als printf (s.a. Konrads Post), KANN es nicht "so sicher wie printf" (das übrigens auch sehr unsicher ist) sein ... schon gar nicht "mindestens".

    Stefan schrieb:

    ...Der Kern meiner Frage war eigentlich, ob die Methode auf die Variablen Argumente zuzugreifen sicher ist, oder ob Gefahr besteht, auf eine verbotene Speicheradresse zuzugreifen....

    Definitiv letzteres.
    Nochmal: warum übergibst Du nicht einfach einen vector (bzw. eine Referenz darauf) ?
    Funktioniert auch nicht anders, ist aber sicher in all den o.g. und weiteren Belangen.
    Schonmal nachgedacht, was passiert, wenn der Aufrufer Folgendes macht:

    myClass peng;
    PrintStrs(2, "Hallo", &peng);
    

    ?

    Gruß,

    Simon2.

    Du kannst bei printf ja auch den Fehler machen, dass du die falsche Anzahl Formatierungszeichen hast, und falsche Typen übergibst.
    Ich fände die v.a.l. einfach elegant, um z.B. ein multidimesionals Array zu dimensionieren:

    void DimArray(int ndims, int size, ...);
    


  • Stefan schrieb:

    Ich fände die v.a.l. einfach elegant, um z.B. ein multidimesionals Array zu dimensionieren:

    Grundsätzlich müssen eleganz und Sicherheit nicht unbedingt gleiche Wege gehen, was IMHO aber kein Grund ist bekanntermaßen unsichere Konstrukte verwendet werden.

    Wem die Vectorübergabe wegen der Initialisierung zu kompliziert erscheint sollte sich mal Boost anschauen (konkret die [assign-Bibliothek](file:///D:/lokal_vc8/boost/libs/assign/doc/index.html)).

    Dann sähe dein Aufruf irgendwie so aus (ungetestet):

    void PrintStrings(const std::vector<std::string>& strings);
    ...
    std::vector<std::string> strings; // <-- Besser um Kopieren zu vermeiden mit Anzahl initialisieren
    strings += "a", "b", "c", "d";
    PrintStrings(strings);
    ...
    


  • asc schrieb:

    Wem die Vectorübergabe wegen der Initialisierung zu kompliziert erscheint sollte sich mal Boost anschauen (konkret die [assign-Bibliothek](file:///D:/lokal_vc8/boost/libs/assign/doc/index.html)).

    Ja, Boost wollte ich auch schon vorschlagen, allerdings nicht assign sondern (konzeptuell ähnlich) format. Mit folgendem Aufruf:

    PrintStrings() % "a" % "b" % "c";
    

    Allerdings besitzt das eine andere Semantik, weil hier keine Parameter an eine Funktion übergeben werden. Das obige Konstrukt müsste irgendwie noch evaluiert werden.



  • Ansonsten könnte man die Funktion PrintStrings ja auch 10 mal überladen, ist sicher und erfordert keine Frickelei 🙂



  • Stefan schrieb:

    ...
    Du kannst bei printf ja auch den Fehler machen, dass du die falsche Anzahl Formatierungszeichen hast, und falsche Typen übergibst....

    "falsche Anzahl an Formatierungszeichen": Stimmt ! Daran hatte ich noch nicht gedacht. Aber das entspricht ja auch den Beispiel von Konrad.
    "falsche Typen" entspricht dabei meinem Beispiel.
    Also: Vielleicht ist es (bis auf die geringere Bekanntheit) damit nicht schlechter als printf() ... aber das wäre für mich noch lange kein positives Qualitätsurteil.

    Gruß,

    Simon2.


Anmelden zum Antworten