Optimierungsbedarf



  • Moin. Habe mit C++ angefangen und mich soweit eingeübt.
    Habe dieses programm zum Zerlegen von Dateien geschrieben

    #include <iostream>
    #include <fstream>
    #include <dir.h>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        // benötigte variablen über jeder schleife deklarieren
        char path[200];
        char *dir = "test";
        char cur_part_path[100];
        ifstream fin;
        ofstream fou;
        size_t limit;
        unsigned long write_pos;
        int filenr, filescreated;
        char tmp;
    
        while (true)
        {
            // nach zu zerlegenden datei fragen.
            fflush(stdin);
            cout << "Datei: "; cin.get(path, sizeof(path));
            if (path == "exit") break;
    
            // zu zerlegende datei öffnen
            ifstream fin (path);
            if (!fin.is_open())
            {
                cout << "Datei existiert nicht oder konnte nicht geöffnet werden!" << endl;
                continue;
            }
    
            // abfragen, wie viele bytes pro part.
            while (true)
            {
                cout << "Bytes pro Part: "; cin >> limit;
                if (limit != 0) break;
                cout << "0 Bytes? Das gäbe unendlich viele Parts." << endl;
            }
    
            if (mkdir(dir) == -1)
            {
                cout << "-> Konnte Verzeichnis für die Parts nicht erstellen."     << endl;
                cout << "   Wahrscheinlich existiert das Zielverzeichnis bereits!" << endl;
            }
                else
            {
                filescreated = 0;
                filenr = 1;
                while (!fin.eof())
                {
                    // pfad zum aktuellen part
                    sprintf(cur_part_path, "%s%s%s%s%d", dir, "/", path, ".part", filenr);
                    cout << cur_part_path << endl;
    
                    write_pos = 0;
                    while (fin.get(tmp))
                    {
                        if (!fou.is_open())
                        {
                            fou.open (cur_part_path);
                            if (!fou.is_open())
                            {
                                cout << "Konnte Part nicht anlegen und zum Schreiben öffnen." << endl;
                                break;
                            }
                            filescreated++;
                        }
    
                        fou.put(tmp);
                        if (++write_pos >= limit) break;
                    }
                    filenr++;
    
                    // wurde für diesen durchlauf kein neuer part angelegt, ist der job erledigt
                    if (!fou.is_open()) break;
                    fou.close();
                }
    
                fin.close();
    
                // prozessverlauf ausgeben
                printf("-> %d Parts erstellt!\n", filescreated);
            }
        }
    
        cin.ignore();
        return 0;
    }
    

    Es wird gefragt, welche Datei zerlegt werden soll.
    Ein Verzeichnis test wird relativ zur working directoty
    angelegt, wo alle Stück-Dateien reinkommen.
    Gibt es noch ein mögliches Risiko zu beachten oder
    etwas für die Perormance zu verbessern?

    Bitte für einen Anfänger erklären.
    Möchte auch weder mit string.h noch sstream.h arbeiten.



  • Sicherheitsrisiko 1: 'fflush(stdin)' erzeugt undefiniertes Verhalten. Verwende lieber cin.ignore(), um den Eingabepuffer zu leeren.

    Sicherheitsrisiko 2: Die Größenüberprüfung von char-Arrays ist praktisch nicht existent. Das bedeutet, daß du relativ schnell über den Verfügbaren Speicherbereich hinausschreiben könntest (gerade der sprintf()-Aufruf sieht da gefährlich aus - du versuchst im Extremfall 215 Zeichen in ein 100-Zeichen-Array zu quetschen). Da bist du mit std::string auf der sicheren Seite.

    Problem 3: Anstatt nur auf is_open() bzw. eof() zu überprüfen, solltest du die komplette Fehler-Palette abfangen (fail()).

    Performance 4: Anstatt jedes Zeichen einzeln durch den Speicher zu jagen, kannst du auch größere Blöcke nehmen und kopieren.



  • Wie darf ich das verstehen, dass fflush() undefiniertes Verhalten hat?
    Kann ich nciht auch nen char Pointer nehmen?



  • sjBlack schrieb:

    Wie darf ich das verstehen, dass fflush() undefiniertes Verhalten hat?

    Genau so: Das Verhalten von fflush( ) auf Eingabestreams ist undefiniert!

    greetz, Swordfish



  • http://www.c-plusplus.net/forum/viewtopic-var-p-is-1146014.html

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        char * test;
        char buffer[100];
        while (true)
        {
            int c; while ((c = getchar())!=EOF && c!='\n');
            cin.get(buffer, sizeof(buffer));
            test = buffer;
            cout << test << endl;
            system("PAUSE");
        }
    
        system("PAUSE");
        return 0;
    }
    

    Bekomme bei der ersten Eingabe nichts ausgegeben.
    Bei den restlichen hingegen schon.
    Woran liegt das?

    // nachtrag
    Bekommt man hier keinen Support? Ist dieses Forum purer Wissensaustausch
    unter Informatikern? Niemand anfängerfreundlich?

    // nachtrag 2

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        char * test;
        char buffer[100];
        int c;
        while (true)
        {
            cin.get(buffer, sizeof(buffer));
            while ((c = getchar())!=EOF && c!='\n');
            test = buffer;
            cout << test << endl;
            system("PAUSE");
        }
    
        system("PAUSE");
        return 0;
    }
    

    Leere den Tastaturpuffer jetzt nach den Eingaben
    und deklariere die int-variable außerhalb der
    Schleife. Jetzt funktioniert es.



  • sjBlack schrieb:

    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1146014.html

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        char * test;
        char buffer[100];
        while (true)
        {
            int c; while ((c = getchar())!=EOF && c!='\n');
            cin.get(buffer, sizeof(buffer));
            test = buffer;
            cout << test << endl;
            system("PAUSE");
        }
    
        system("PAUSE");
        return 0;
    }
    

    Bekomme bei der ersten Eingabe nichts ausgegeben.
    Bei den restlichen hingegen schon.
    Woran liegt das?

    Das liegt daran, daß vor der ersten Eingabe noch nichts im Puffer stand, was die while-Schleife entsorgen könnte.

    // nachtrag
    Bekommt man hier keinen Support? Ist dieses Forum purer Wissensaustausch
    unter Informatikern? Niemand anfängerfreundlich?

    Klar bekommst du hier Unterstützung, aber schau mal auf die Uhr 😉

    PS: Klar kannst du char-Pointer verwenden, wenn du unbedingt Wert darauf legst. Aber dann mußt du ständig selber kontrollieren, ob du wirklich genug Platz für die unterzubringenden Daten hast (wenn du das vergisst: undefiniertes Verhalten).

    PPS: Und "undefiniertes Verhalten" bedeutet, daß du nicht vorhersagen kannst, was das Programm macht - es kann sein, daß alles gut geht, aber es kann auch sein, daß du damit deine Festplatte in einen Klumpen Altmetall verwandelst.



  • aber es kann auch sein, daß du damit deine Festplatte in einen Klumpen Altmetall verwandelst.
    

    Das ist zum Glück dann doch eher unwahrscheinlich 😃

    Grüße,

    Martin



  • aber es kann auch sein, daß du damit deine Festplatte in einen Klumpen Altmetall verwandelst.
    

    Das ist zum Glück dann doch eher unwahrscheinlich 😃

    Grüße,

    Martin



  • JimmydaMage schrieb:

    Das ist zum Glück dann doch eher unwahrscheinlich 😃

    Unwahrscheinlich vielleicht, aber technisch durchaus erlaubt.

    (eigentlich wollte ich ja schreiben "daß du damit den vierten Weltkrieg auslöst" :D)


Anmelden zum Antworten