array vs vector



  • Es macht durchaus Sinn diese Sicherheitsfeatures einzubauen. Standardmaessig sind sie deshalb aktiv, da MS davon ausgeht dass Leute die es wollen ja ausschalten koennen und die Leute die das nicht interessiert, die sind mit den Ueberpruefungen besser dran.

    Ob das Sinn macht ist natuerlich Diskussionswuerdig, aber das ist der Status Quo. Warum nicht mal Doku zum eigenen Compiler lesen...? Mich stoerts nicht, da ich es ja abdrehen kann wenn ich es brauche...



  • Ich finde das auch nicht so schlimm. Abgesehen davon ist der Zug abgefahren bezüglich opt-in vs. opt-out.



  • Naja so prickelnd finde ich das von MS nicht. Das hat mir mal nen schönen Fehler eingehandelt. In einer DLL hatte ich mal testweise den Define drinne, die Hauptanwendnung hatte sie nicht. Nun gabs dauernd Laufzeitfehler. Gut, selber Schuld, aber bis man sowas manchmal entdeckt^^ Von daher mag ich dieses rumstellen per define als Compile-Schalter perse nicht. Das ist ja nicht mal als normale Option in den Eigenschaften drinne. Und auf die Laufzeit kann es sioch ja wirklich negativ ausüben, muss natürlich nicht.

    bezüglich opt-in vs. opt-out.

    Ich steh grad aufm Schlauch^^ Was willst du uns damit sagen? 🙂

    Warum nicht mal Doku zum eigenen Compiler lesen...?

    Wie weit bist du denn in der MSDN voran geschritten? Ist ja nicht gerade wenig 😃
    Ich muss sagen, dass der operator[] ne Überprüfung macht, habe ich auch net gewusst. Ich kannte auch nur das, was in meinem STL-Buch steht: nämlich das das at prüft und [] eben nicht! (und für so ein Buch hab ich 30 Euro gelöhnt^^)

    Aber aufregen bringt ja nix. is halt so. Und deswegen wieder anfangen alles per Hand zu allokieren: sicher nicht!



  • Pellaeon schrieb:

    Warum nicht mal Doku zum eigenen Compiler lesen...?

    Wie weit bist du denn in der MSDN voran geschritten? Ist ja nicht gerade wenig 😃

    😃 Ich glaub der macht den ganzen Tag nix anderes als Dokus, Bücher und Diskussionen zu lesen.



  • Ich sehe den Sinn dieses Range Checks nicht. Der wirft ja nicht mal eine exception. Als release schmiert das Programm einfach ab (Visual C++ 2008).

    vector<int> v(10);
    
    	try
    	{
    		v[10] = 0;
    	}
    	catch(exception &ex)
    	{
    		cout << ex.what();
    	}
    	catch(...)
    	{
    	}
    


  • Schutz gegen Hacker?



  • Stefan schrieb:

    Ich sehe den Sinn dieses Range Checks nicht. Der wirft ja nicht mal eine exception. Als release schmiert das Programm einfach ab (Visual C++ 2008).

    Sei froh! Ohne Rangchecks läuft das Programme einfach durch, ohne das irgendwas passiert (ja, ich weiß undefiniertes Verhalten, bei mir, mit meinem Kompiler, auf meinem Computer, zu eben dieser Uhrzeit, an eben diesem Ort, bei dieser spezifischen Raumtemparatur passiert nichts). Es wäre doch fatal, wenn solche riesigen Programmierfehler sich in keinster Weise bemerkbar machen. Ein kleiner Programmierfehler in der Software fliegt also eventuell erst auf, wenn das Produkt schon beim Kunden ist. Und dann hat man noch das Problem, dass man nicht weiß, wo der Fehler aufgetreten ist.
    Selbst, wenn sich eine Range-Überschreitung "nur" in einem Absturz bemerkbar macht, so lässt sich der Ort des Fehlers doch stark einschränken. In jedem größeren Software Projekt werden die Komponenten ja einzeln getestet. Je nach dem welcher Test dann abstürzt, kennt man dann die defekte Komponente.



  • Ja, aber eine Exception wär trotzdem besser...



  • Geht auch: _SCL_SECURE_THROWS.

    Gruß
    Don06



  • Nexus schrieb:

    Ja, aber eine Exception wär trotzdem besser...

    exceptions kann man ignorieren.

    deshalb: nie nie nie nie nie eine exception werfen wenn es sich um logik fehler handelt. zumindest keine die man fangen kann. sonst kommt sowas raus was man in java hat, dass fehler einfach immer ignoriert werden "weil das programm ja eh problemlos durchlaeuft".



  • const_reference operator[](size_type _Pos) const
    		{	// subscript nonmutable sequence
    
     #if _HAS_ITERATOR_DEBUGGING
    		if (size() <= _Pos)
    			{
    			_DEBUG_ERROR("vector subscript out of range");
    			_SCL_SECURE_OUT_OF_RANGE;
    			}
     #endif /* _HAS_ITERATOR_DEBUGGING */
    		_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
    
    		return (*(_Myfirst + _Pos));
    		}
    
    	reference operator[](size_type _Pos)
    		{	// subscript mutable sequence
    
     #if _HAS_ITERATOR_DEBUGGING
    		if (size() <= _Pos)
    			{
    			_DEBUG_ERROR("vector subscript out of range");
    			_SCL_SECURE_OUT_OF_RANGE;
    			}
     #endif /* _HAS_ITERATOR_DEBUGGING */
    		_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
    
    		return (*(_Myfirst + _Pos));
    		}
    

    also das ist der code zum []-operator mit dem range check...



  • Shade Of Mine schrieb:

    Nexus schrieb:

    Ja, aber eine Exception wär trotzdem besser...

    exceptions kann man ignorieren.

    deshalb: nie nie nie nie nie eine exception werfen wenn es sich um logik fehler handelt. zumindest keine die man fangen kann. sonst kommt sowas raus was man in java hat, dass fehler einfach immer ignoriert werden "weil das programm ja eh problemlos durchlaeuft".

    Warum machts dann vector.at? http://msdn.microsoft.com/en-us/library/c6kkh778(VS.80).aspx

    If _Off is greater than the size of the vector, at throws an exception.



  • Bitte geben Sie einen schrieb:

    Warum machts dann vector.at?

    Weil man bei .at() explizit sagt "ich bin zu dumm auf size() zu pruefen".



  • Programmiert wirklich jemand so?

    try{
      while(true)
        vector.at
    }
    catch(...){
    }
    


  • Bitte geben Sie einen schrieb:

    Programmiert wirklich jemand so?

    try{
      while(true)
        vector.at
    }
    catch(...){
    }
    

    jein, natuerlich nicht so in einer schleife.
    aber wenn das programm eine exception wirft und ich fange die exception einfach und tue nichts und das programm laeuft "fehlerlos" durch - dann ist das problem geloest und ich kann es vergessen.

    das sieht man zB in java gut, wo dank checked exceptions es massig try{foo()}catch(Exception e){} bloecke gibt.

    die wirkliche frage bei exceptions ist aber auch: wie soll ich darauf reagieren?
    wenn ich einfach mist gebaut habe und das programm sachen macht die es nie machen darf, zB out of bounds array zugriffe - wie soll ich darauf sinnvoll reagieren? eigentlich muss ich jetzt debuggen und die anwendung nicht mehr weiter ausfuehren - denn ich kann nicht garantieren dass alle komponenten in einem gueltigen zustand sind. wenn man jetzt normal weiter macht und den fehler ignoriert, kann man nciht mehr das fehlerfreie verhalten der software garantieren.

    deshalb: nie logik fehler ignorieren.

    hier hilft uebrigens auch keine VM wie java oder .net



  • @ Shade Of Mine:
    Du hast natürlich Recht, grundsätzlich ist es sicherer, das Programm direkt zu beenden. Von vernünftigen Anwender sollte man allerdings erwarten können, dass sie ihr Programm nicht mit sinnlosen catch(...) -Blöcken füllen (ich weiss, die Realität sieht anders aus). Trotzdem ist es ja schlussendlich das Problem des Anwenders, wenn er unfähig ist, auf Exceptions zu reagieren.

    Exceptions haben aber den Vorteil, dass wenn man sie nicht fängt, man gerade sieht, wo sie aufgetreten sind und zusätzlich noch Information über den String erhält. Bei direktem Programmabsturz muss man evtl. mühsam durchdebuggen, bis man die Ursache findet. Aber es ist halt sicherer, weil der Absturz nicht ignoriert werden kann.

    Shade Of Mine schrieb:

    deshalb: nie nie nie nie nie eine exception werfen wenn es sich um logik fehler handelt. zumindest keine die man fangen kann.

    Man kann jede Exception fangen. Oder was meinst du?

    Und wenn man alles idiotensicher machen will, dürfte man im Prinzip nie Exceptions werfen, weil alle ignoriert werden können. Dann ist das Feature der Exceptions von C++ in deinen Augen unnötig oder sogar gefährlich? Oder wieso meinst du, betrifft das nur Logikfehler? Weil die eher ignoriert werden als andere Exceptions?



  • Nexus schrieb:

    Bei direktem Programmabsturz muss man evtl. mühsam durchdebuggen, bis man die Ursache findet. Aber es ist halt sicherer, weil der Absturz nicht ignoriert werden kann.

    ein assert sollte automatisch den debugger starten. wenn nicht, ist irgendwas falsch konfiguriert.

    und dann ist man mit dem debugger genau dort wo der fehler aufgetreten ist und kann einen backtrace machen oder einfach mal durchsteppen und schauen was los ist (vorallem hat man den aktuellen kontext, also alle variablen, etc.)

    Und wenn man alles idiotensicher machen will, dürfte man im Prinzip nie Exceptions werfen, weil alle ignoriert werden können. Dann ist das Feature der Exceptions von C++ in deinen Augen unnötig oder sogar gefährlich? Oder wieso meinst du, betrifft das nur Logikfehler? Weil die eher ignoriert werden als andere Exceptions?

    manche fehler mag ich ignorieren koennen. manche fehler sind keine schlimmen fehler, auf manche fehler kann ich reagieren.

    auf ein out of bounds _kann_ ich nicht reagieren, es ist nicht moeglich darauf zu reagieren, denn es heisst, dass mein code nicht dass tut was er soll. ich koennte maximal mich automatisch updaten und neustarten, aber mehr? ne...



  • bei Datenbankanwendungen würde ich bei jedem Fehler erwarten, dass sie noch ein Rollback macht.



  • Shade Of Mine schrieb:

    auf ein out of bounds _kann_ ich nicht reagieren, es ist nicht moeglich darauf zu reagieren, denn es heisst, dass mein code nicht dass tut was er soll. ich koennte maximal mich automatisch updaten und neustarten, aber mehr? ne...

    Wenn man in seinem eigenen Code die Arraygrenzen überschreitet, ist das natürlich klar. Aber es könnte ja auch sein, dass vom Benutzer Eingaben erwartet werden (wobei man hier vielleicht besser mit if überprüft).

    Shade Of Mine schrieb:

    manche fehler mag ich ignorieren koennen. manche fehler sind keine schlimmen fehler, auf manche fehler kann ich reagieren.

    Ja, aber generell ist es nicht unbedingt empfehlenswert, Fehler zu ignorieren, auch wenn sie auf den Blick nicht schlimm aussehen...

    Shade Of Mine schrieb:

    ein assert sollte automatisch den debugger starten. wenn nicht, ist irgendwas falsch konfiguriert.

    Im Release-Modus merkt man trotzdem nichts davon - also auch beim Ausführen der fertigen Anwendung nicht (es ist ja nicht immer gesagt, dass schön debuggt wird). Naja, sorry für die Spitzfindigkeiten, ich verstehe schon, was du meinst 😉



  • Hallo,

    ich habe den Code von "asmcode" verwendet, um den Performancetest zwischen Vektoren und Arrays nachzuvollziehen. Zusätzlich habe ich noch den von "Shadow Of Mine" empfohlen Schalter gesetzt. Zum Kompilieren habe ich den Defaultcompiler von MSV 2005 verwendet.

    Leider bringt der Schalter keine messbare Performanceverbesserung. Hat jemand eine Erklärung?

    Viele Grüße!

    Test Programm:

    #include <vector>
    #include <iostream>
    #include <windows.h>
    
    void foo()
    {
    
    	LONGLONG g_Frequency, g_CurentCount, g_LastCount;
    
        //Frequenz holen
        if (!QueryPerformanceFrequency((LARGE_INTEGER*)&g_Frequency))
            std::cout << "Performance Counter nicht vorhanden" << std::endl;
    
        //1. Messung
        QueryPerformanceCounter((LARGE_INTEGER*)&g_CurentCount);
    
        int max=50000;
        std::vector<int> a(max);
        for (int i=0; i<=max-2; i++)
        {
            int x,Min = i;
            for (int j=i+1; j<=max-1; j++)
                if (a[j]<a[Min]) Min = j;
            x = a[i]; a[i] = a[Min]; a[Min] = x;
        }
    
        //2. Messung
        QueryPerformanceCounter((LARGE_INTEGER*)&g_LastCount);
    
        double dTimeDiff = (((double)(g_LastCount-g_CurentCount))/((double)g_Frequency));
        std::cout << "Zeit: " << dTimeDiff << std::endl;
    }
    
    void bar()
    {
        LONGLONG g_Frequency, g_CurentCount, g_LastCount;
    
        //Frequenz holen
        if (!QueryPerformanceFrequency((LARGE_INTEGER*)&g_Frequency))
            std::cout << "Performance Counter nicht vorhanden" << std::endl;
    
        //1. Messung
        QueryPerformanceCounter((LARGE_INTEGER*)&g_CurentCount);
    
        int max=50000;
        int* a = new int[max];
        for (int i=0; i<=max-2; i++)
        {
            int x,Min = i;
            for (int j=i+1; j<=max-1; j++)
                if (a[j]<a[Min]) Min = j;
            x = a[i]; a[i] = a[Min]; a[Min] = x;
        }
    
        //2. Messung
        QueryPerformanceCounter((LARGE_INTEGER*)&g_LastCount);
    
        double dTimeDiff = (((double)(g_LastCount-g_CurentCount))/((double)g_Frequency));
        std::cout << "Zeit: " << dTimeDiff << std::endl;
    }
    
    int main(int argc, char**argv)
    {
    	#ifdef _SECURE_SCL
    	std::cout << " _SECURE_SCL Value: " << _SECURE_SCL <<std::endl;
    	#endif
        foo();
        bar();
    
    	#define _SECURE_SCL 0
    
    	#ifdef _SECURE_SCL
    	std::cout << " _SECURE_SCL Value: " << _SECURE_SCL <<std::endl;
    	#endif
        foo();
        bar();
    
    	getchar();
    }
    

    Ausgabe

    _SECURE_SCL Value: 1
    Zeit: 8.40913
    Zeit: 1.83019
    _SECURE_SCL Value: 0
    Zeit: 8.3748
    Zeit: 1.82929
    

Anmelden zum Antworten