Ich habe kürzlich gelesen, dass ein Überlauf von vorzeichenbehafteten Ganzzahlen in C und C++ zu undefiniertem Verhalten führt:
Wenn während der Auswertung eines Ausdrucks das Ergebnis nicht mathematisch definiert ist oder nicht im Bereich darstellbarer Werte für seinen Typ liegt, ist das Verhalten undefiniert.
Ich versuche gerade, den Grund für das undefinierte Verhalten hier zu verstehen. Ich dachte, dass hier undefiniertes Verhalten auftritt, weil die Ganzzahl beginnt, den Speicher um sich herum zu manipulieren, wenn sie zu groß wird, um in den zugrunde liegenden Typ zu passen.
Also beschloss ich, ein kleines Testprogramm in Visual Studio 2015 zu schreiben, um diese Theorie mit dem folgenden Code zu testen:
#include <stdio.h>
#include <limits.h>
struct TestStruct
{
char pad1[50];
int testVal;
char pad2[50];
};
int main()
{
TestStruct test;
memset(&test, 0, sizeof(test));
for (test.testVal = 0; ; test.testVal++)
{
if (test.testVal == INT_MAX)
printf("Overflowing\r\n");
}
return 0;
}
Ich habe hier eine Struktur verwendet, um Schutzmaßnahmen von Visual Studio im Debugging-Modus wie das temporäre Auffüllen von Stack-Variablen usw. zu verhindern. Die Endlosschleife sollte mehrere Überläufe von verursachen test.testVal
und das tut es tatsächlich, allerdings ohne andere Folgen als den Überlauf selbst.
Ich habe mir den Speicherauszug angesehen, während ich die Überlauftests mit folgendem Ergebnis ausgeführt habe (test.testVal
hatte eine Speicheradresse von 0x001CFAFC
):
0x001CFAE5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x001CFAFC 94 53 ca d8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Wie Sie sehen, blieb der ständig überlaufende Speicher um das int “unbeschädigt”. Ich habe dies mehrmals mit ähnlicher Ausgabe getestet. Nie wurde irgendein Speicher um das überlaufende int herum beschädigt.
was geschieht hier? Warum wird der Speicher um die Variable herum nicht beschädigt? test.testVal
? Wie kann dies zu undefiniertem Verhalten führen?
Ich versuche, meinen Fehler zu verstehen und warum während eines Ganzzahlüberlaufs keine Speicherbeschädigung auftritt.
Sie erwarten eine Definition des Verhaltens, das “undefiniert” ist?! Ihnen wird ausdrücklich gesagt, dass es keine vernünftigen Erwartungen gibt, die Sie haben können, daher kann sich das Verhalten möglicherweise nicht von dem unterscheiden, was Sie erwarten dürfen.
– Kerrek SB
19. Mai 2016 um 14:01 Uhr
Der Ganzzahlüberlauf wirkt sich nicht auf den angrenzenden Speicher aus.
– Saschoalm
19. Mai 2016 um 14:01 Uhr
@NathanOliver, es schadet nicht, über undefiniertes Verhalten nachzudenken. Ich persönlich finde es sehr nützliche Übung.
– SergejA
19. Mai 2016 um 14:04 Uhr
@Olaf UB hat einen Grund, und ich versuche, das herauszufinden. Das Bild enthält keinen entscheidenden Teil der Frage, sondern dient eher der grafischen Veranschaulichung meiner Testergebnisse. Alles im Bild, auch der verwendete Code, wurde als Klartext gepostet.
– Winz
19. Mai 2016 um 14:08 Uhr
Diese Frage abzulehnen ist meiner Meinung nach völlig falsch. OP zeigt tatsächlich einen sehr gesunden Wunsch zu verstehen, anstatt blind zu folgen.
– SergejA
19. Mai 2016 um 14:13 Uhr