Wie man std :: vector’s operator kompiliert macht, indem man Grenzen eingibt, indem man DEBUG eingibt, aber nicht in RELEASE

Ich verwende Visual Studio 2008.

Ich bin mir bewusst, dass std :: vector hat Grenzen mit der at () -function und hat undefiniertes Verhalten, wenn Sie versuchen, etwas mit dem Operator [] falsch (außerhalb des Bereichs) zugreifen.

Ich bin neugierig, ob es möglich ist, mein Programm mit der Überprüfung der Grenzen zu kompilieren. Auf diese Weise würde der Operator [] die function at () verwenden und einen std :: out_of_range casting, wenn etwas außerhalb der Grenzen liegt.

Der Freigabemodus würde ohne Einschränkungen für den Operator [] kompiliert, so dass die performance nicht beeinträchtigt wird.

Ich habe darüber nachgedacht, weil ich eine App, die mit Borland C ++ geschrieben wurde, zu Visual Studio migriere und in einem kleinen Teil des Codes, den ich habe (mit i = 0, j = 1):

v[i][j]; //v is a std::vector<std::vector > 

Die Größe des Vektors ‘v’ ist [0] [1] (also Element 0 des Vektors hat nur ein Element). Das ist undefiniertes Verhalten, ich weiß, aber Borland kehrt hier zurück, VS stürzt ab. Ich mag den Absturz besser als die Rückgabe von 0, also wenn ich mehr “Abstürze” durch die std :: out_of_range Exception bekommen könnte, würde die Migration schneller abgeschlossen werden (so würde es weitere Fehler aufdecken, die Borland versteckt hat).

In Visual Studio 2005 und 2008 werden bounds-check-on- operator[] standardmäßig sowohl in Debug- als auch in Release-Builds verwendet.

Das Makro, um dieses Verhalten zu steuern, ist _SECURE_SCL . Setzen Sie es auf 0, um die Überprüfung der Grenzen zu deaktivieren.

Ihr aktueller Plan in VS2010 besteht darin, die Überprüfung von Grenzen standardmäßig in Release-Builds zu deaktivieren, aber im Debug-Modus beizubehalten. (Das Makro wird auch in _ITERATOR_DEBUG_LEVEL umbenannt. Ich weiß nicht, ob es eine formelle Dokumentation darüber gibt, aber es wurde hier und hier erwähnt )

Aktivieren Sie das Flag _GLIBCXX_DEBUG, um die Überprüfung von STL-Containern zu überprüfen, wie hier beschrieben: http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html

Ich habe das zu früh gefragt, aber ich schreibe trotzdem die Antwort, also teile ich etwas Wissen mit.

Das in Visual Studio implementierte STL-Steuerelement überprüft beim Kompilieren im Debugmodus bereits die Grenzen. Dies kann an der Kopfzeile gesehen werden:

 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 gibt es die Grenzen, die nach der Vektorklasse suchen. Ich habe mir keine anderen Behälter angesehen, aber ich bin zuversichtlich, dass sie denselben Mechanismus haben.

Ich habe momentan keinen Zugriff auf eine Windows-Maschine. Aber wenn ich mir die STL-Implementierung ansehe, die mit g ++ auf meinem Mac OS X-Rechner geliefert wird, von /usr/include/c++/4.0.0/bits/stl_vector.h:

  // element access /** * @brief Subscript access to the data contained in the %vector. * @param n The index of the element for which data should be * accessed. * @return Read/write reference to data. * * This operator allows for easy, array-style, data access. * Note that data access with this operator is unchecked and * out_of_range lookups are not defined. (For checked lookups * see at().) */ reference operator[](size_type __n) { return *(begin() + __n); } 

Keine Überprüfung durchgeführt, Ereignis im DEBUG-Modus. Nein _GLIBCXX_DEBUG marcro ist hier in diesem Code ausgecheckt.

Sehen Sie in Ihrer eigenen STL-Implementierung, die mit MSVC geliefert wird, und sehen Sie, was getan wird. Wenn auf keinen Fall eine Überprüfung durchgeführt wird, haben Sie keine andere Wahl, als at () zu verwenden. 🙁

C ++ definiert den Vektoroperator [] so, dass er wegen der Geschwindigkeit keine Ausnahme austriggers.

Ich rate Ihnen, die Anwendung in Debug Configuration für eine Weile zu testen, bis Sie das Vertrauen gewinnen, dass große “versteckte” Fehler verschwunden sind.