Der folgende Code funktioniert im Debugmodus einwandfrei, da _BitScanReverse64 so definiert ist, dass es 0 zurückgibt, wenn kein Bit gesetzt ist. Unter Berufung auf MSDN: (Der Rückgabewert ist) “Nicht Null, wenn Index gesetzt wurde, oder 0, wenn keine gesetzten Bits gefunden wurden.”
Wenn ich diesen Code im Release-Modus kompiliere, funktioniert er immer noch, aber wenn ich Compiler-Optimierungen wie \O1 oder \O2 aktiviere, ist der Index nicht Null und die assert()
scheitert.
#include <iostream>
#include <cassert>
using namespace std;
int main()
{
unsigned long index = 0;
_BitScanReverse64(&index, 0x0ull);
cout << index << endl;
assert(index == 0);
return 0;
}
Ist das das beabsichtigte Verhalten? Ich verwende Visual Studio Community 2015, Version 14.0.25431.01 Update 3. (Ich habe cout drin gelassen, damit der Variablenindex bei der Optimierung nicht gelöscht wird). Gibt es auch eine effiziente Problemumgehung oder sollte ich diesen Compiler einfach nicht direkt verwenden?
Das sofortige Initialisieren des Index macht hier keinen Unterschied, da _BitScanReverse die Initialisierung durchführt.
– Camleon
27. Dezember 2016 um 20:11 Uhr
Wenn Sie sagen “das Programm stürzt ab”, meinen Sie das
assert
scheitert, oder? Es ist schon eine Weile her, seit ich VS verwendet habe, aber sollte das nichtassert
bei Release-Builds deaktiviert werden?– Eran
27. Dezember 2016 um 20:16 Uhr
Auf der Seite von Microsoft zu _BitScanReverse64 steht das nicht
index
wird gesetzt, wenn kein Bit gesetzt ist; es sagt nurindex
wird mit einem Wert gesetzt, wenn ein Bit gesetzt ist. Wenn also kein Bit gesetzt ist, könnte _BitScanReverse64 gerade verlassen werdenindex
allein und es bleibt mit dem, was es ursprünglich hatte.– Altainien
27. Dezember 2016 um 20:21 Uhr
@Altainia hat imo die richtige Antwort. Sie sollten den Rückgabewert von überprüfen
_BitScanReverse64
. Wenn es null ist, wird der Wert vonindex
ist undefiniert (zumindest in der Dokumentation). Angenommen, weil nur eine Rückgabe ungleich Null anzeigtindex
war eingestellt.– Eran
27. Dezember 2016 um 20:29 Uhr
index
wird auf 0 initialisiert, aber_BitScanReverse64
könnte es intern ändern. Die nicht optimierte Version wird möglicherweise eingestelltindex
auf Null, wenn keine 1 gefunden wird, aber die optimierte Version lässt diesen Teil weg, um Zeit zu sparen. Beide stimmen mit den Dokumenten überein (“Nicht Null, wenn Index gesetzt wurde, oder 0, wenn keine gesetzten Bits gefunden wurden.”) und die optimierte Version macht weniger und ist daher schneller.– Eran
27. Dezember 2016 um 20:36 Uhr