Ich habe eine einfache rekursive Funktion RCompare(), die eine komplexere Funktion Compare() aufruft, die vor dem rekursiven Aufruf zurückgibt. Jede Rekursionsebene verwendet 248 Byte Stack-Speicherplatz, der viel mehr als nötig erscheint. Hier ist die rekursive Funktion:Warum wird so viel Stapelspeicher für jede Rekursion verwendet?
void CMList::RCompare(MP n1) // RECURSIVE and Looping compare function
{
auto MP ne=n1->mf;
while(StkAvl() && Compare(n1=ne->mb))
RCompare(n1); // Recursive call !
}
StkAvl() ist ein einfacher Stapelspeicher Prüffunktion, die die Adresse eines Auto-Variable auf den Wert eine Adresse in der Nähe des Endes der in einer statischen Variablen gespeicherten Stapel vergleichen.
Es scheint mir, dass die einzigen Dinge in jeder Rekursion zum Stapel hinzugefügt sind zwei Zeigervariablen (MP ist ein Zeiger auf eine Struktur) und die Sachen, die ein Funktionsaufruf speichert, ein paar gespeicherte Register, Basiszeiger, Rückkehr Adresse, usw., alle 32-Bit (4 Byte) -Werte. Es gibt keine Möglichkeit, dass es 248 Bytes ist, oder?
ich keine nicht, wie eigentlich auf dem Stapel in einer sinnvollen Art und Weise in Visual Studio 2008.
Dank aussieht
hinzugefügt Demontage:
CMList::RCompare:
0043E000 push ebp
0043E001 mov ebp,esp
0043E003 sub esp,0E4h
0043E009 push ebx
0043E00A push esi
0043E00B push edi
0043E00C push ecx
0043E00D lea edi,[ebp-0E4h]
0043E013 mov ecx,39h
0043E018 mov eax,0CCCCCCCCh
0043E01D rep stos dword ptr es:[edi]
0043E01F pop ecx
0043E020 mov dword ptr [ebp-8],edx
0043E023 mov dword ptr [ebp-14h],ecx
0043E026 mov eax,dword ptr [n1]
0043E029 mov ecx,dword ptr [eax+20h]
0043E02C mov dword ptr [ne],ecx
0043E02F mov ecx,dword ptr [this]
0043E032 call CMList::StkAvl (41D46Fh)
0043E037 test eax,eax
0043E039 je CMList::RCompare+63h (43E063h)
0043E03B mov eax,dword ptr [ne]
0043E03E mov ecx,dword ptr [eax+1Ch]
0043E041 mov dword ptr [n1],ecx
0043E044 mov edx,dword ptr [n1]
0043E047 mov ecx,dword ptr [this]
0043E04A call CMList::Compare (41DA05h)
0043E04F movzx edx,al
0043E052 test edx,edx
0043E054 je CMList::RCompare+63h (43E063h)
0043E056 mov edx,dword ptr [n1]
0043E059 mov ecx,dword ptr [this]
0043E05C call CMList::RCompare (41EC9Dh)
0043E061 jmp CMList::RCompare+2Fh (43E02Fh)
0043E063 pop edi
0043E064 pop esi
0043E065 pop ebx
0043E066 add esp,0E4h
0043E06C cmp ebp,esp
0043E06E call @ILT+5295(__RTC_CheckEsp) (41E4B4h)
0043E073 mov esp,ebp
0043E075 pop ebp
0043E076 ret
Warum 0E4h?
Mehr Info:
class mch // match node structure
{
public:
T_FSZ c1,c2; // file indexes
T_MSZ sz; // match size
enum ntyp typ; // type of node
mch *mb,*mf; // pointers to next and previous match nodes
};
typedef mch * MP; // for use in casting (MP) x
Sollte eine einfache alte Zeiger richtig? Die gleichen Zeiger sind in der Struktur selbst und sie sind nur normale 4-Byte-Zeiger.
Edit: Hinzugefügt:
#pragma check_stack(off)
void CMList::RCompare(MP n1) // RECURSIVE and Looping compare function
{
auto MP ne=n1->mf;
while(StkAvl() && Compare(n1=ne->mb))
RCompare(n1); // Recursive call !
} // end RCompare()
#pragma check_stack()
Aber es hat nichts ändern. :(
Nun, was
Konnten Sie eine sizeof (MP) nur tun, um zu überprüfen, wie viel Speicher der Compiler denkt, dass er für den intelligenten Zeiger zuordnen sollte, zeigen Sie die Definition von MP? – Arve
Es ist kein "intelligenter Zeiger". Nick D hat das Problem gefunden. – Harvey
Das sieht wie eine Debug-Disassembly aus. Wird der zusätzliche Stack-Speicherplatz auch in einem Release-Build verwendet? Haben Sie versucht, die Compiler-Codegenerierungsoptionen (Projekteigenschaften -> Konfigurationseigenschaften -> C/C++ -> Codegenerierung) zu ändern? Zusätzlicher Stapelspeicher, der verwendet wird, wenn Sie eine Zeigervariable hinzufügen, klingt definitiv wie ein Pufferüberlauf-Prüfmechanismus des Compilers. – Niki