Forum: Compiler & IDEs Variablen auf Stack, Leerräume


von Thomas W. (thomas_v2)


Lesenswert?

Hallo,
ich habe mir gerade mal angesehen, wie bei einem C-Programm die 
Variablen auf dem Stack abgelegt werden.

Testfunktion
1
void test()
2
{
3
    int var1;                   // -0c
4
    unsigned char var2[8];      // [0] = -1c, [1] = -1b, [7] = -15
5
    struct tt {
6
        unsigned int aa;        // -34
7
        unsigned int bb;        // -30
8
        unsigned int cc;        // -2c
9
        unsigned int dd;        // -28
10
    } stt;
11
    int var3;                   // -40
12
}

Im Kommentar ist der Adressoffset zu ebp angegeben.

Dabei ist mir aufgefallen, dass zwischen einzelnen Variablen auf dem 
Stack immer 8 Bytes freigelassen werden. Hat das einen bestimmten Grund?

Getestet habe ich mit VS2013 unter 32-Bit Windows (x86).

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Thomas W. schrieb:
> Hat das einen bestimmten Grund?

Je nach Compilereinstellung können das "stack guards" sein, mit denen 
die Runtime-Library Stackfehler und Variablenläufe erkennen kann.

von Thomas W. (thomas_v2)


Lesenswert?

Rufus Τ. F. schrieb:

> Je nach Compilereinstellung können das "stack guards" sein, mit denen
> die Runtime-Library Stackfehler und Variablenläufe erkennen kann.

Dieser "Security Cookie" liegt an offset -4, dazwischen auch wieder 4 
Bytes frei und dann kommt die erste Variable.

Ja, zur Zeit übersetze in mit den Debug-Einstellungen. Dieser freie 
Platz führt doch sogar eher dazu, dass ich eventuelle Fehler nicht 
entdecke, weil nicht eine andere Variable, sondern unbenutzer Bereich 
überschrieben wird.

von Dumdi D. (dumdidum)


Lesenswert?

Alignment?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Thomas W. schrieb:
> Dieser freie Platz führt doch sogar eher dazu, dass ich eventuelle
> Fehler nicht entdecke, weil nicht eine andere Variable, sondern
> unbenutzer Bereich überschrieben wird.

Beim Verlassen eines Blocks wird vom Runtime-Code der freie Platz 
überprüft, ob er sich geändert hat.

D.h. beim Betreten eines Blocks wird der benutzte Bereich des Stacks mit 
einem definierten Bitmuster (0xCD, wenn ich mich recht erinnere) 
initialisiert, und beim Verlassen des Blocks das Vorhandensein dieses 
Bitmusters in den Lücken geprüft.

von Thomas W. (thomas_v2)


Lesenswert?

Rufus Τ. F. schrieb:

> D.h. beim Betreten eines Blocks wird der benutzte Bereich des Stacks mit
> einem definierten Bitmuster (0xCD, wenn ich mich recht erinnere)
> initialisiert, und beim Verlassen des Blocks das Vorhandensein dieses
> Bitmusters in den Lücken geprüft.

Ah, ok.

Der Anfang der Funktion sieht bei mir so aus:
1
push    ebp
2
mov     ebp, esp
3
sub     esp, 104h
4
push    ebx
5
push    esi
6
push    edi
7
lea     edi, [ebp+var_104]
8
mov     ecx, 41h
9
mov     eax, 0CCCCCCCCh
10
rep stosd
11
mov     eax, __security_cookie
12
xor     eax, ebp
13
mov     [ebp+var_4], eax
14
mov     [ebp+var_C], 0AAAAh
Die letzte Anweisung ist die erste aus meinem C-Code (var1 = 0xaaaa;)

D.h. da werden zu Beginn 260 Bytes auf dem Stack mit 0xcc beschrieben

Wobei dann die Stack-Check Funktion wissen müsste, an welcher Stelle die 
Variablen auf dem Stack abgelegt werden, um auch die Lücken zu 
überprüfen. Dazu sieht mir diese Funktion aber zu kurz aus.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Thomas W. schrieb:
> Dazu sieht mir diese Funktion aber zu kurz aus.

Die ist es ja auch nicht. Die Überprüfung übernimmt eine Funktion, die 
erst nach dem Verlassen des Blocks aufgerufen wird.

von Thomas W. (thomas_v2)


Lesenswert?

Es ist die Compileroption /RTC die das verursacht. Ohne diese sind auch 
keine Lücken mehr vorhanden.

https://msdn.microsoft.com/de-de/library/8wtf2dfz.aspx

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.