Сообщение Re[3]: А почему бы не сделать стек еще умнее? от 15.11.2016 11:49
Изменено 15.11.2016 11:50 Pavel Dvorkin
Здравствуйте, _smit, Вы писали:
Почти все верно
_>
В действительности по крайней мере VC++ так не делает. Память для стека отводится при входе в функцию, хотя переменные, конечно, "логически"перестают существовать при выходе на свою "}". Однако рпмять при этом не освобождается.
"Идейно" было бы правильно сделать, как отметили Вы, но в реальности делается иначе.
В остальном вполне согласен.
Почти все верно
_>
_>void foo()
_>{// выделился фрейм 1 на стеке и вначале фрейма сохранился адрес программного кода куда надо возвратиться при выходе из функции,
_> {// выделился фрейм 2 на стеке
_> int k;
_> int d;
_> } // фрейм 2 освободился на стеке, k и d освободились (разрушились)
_>}// фрейм 1 освободился на стеке, str и b освободились (разрушились)
_>В действительности по крайней мере VC++ так не делает. Память для стека отводится при входе в функцию, хотя переменные, конечно, "логически"перестают существовать при выходе на свою "}". Однако рпмять при этом не освобождается.
"Идейно" было бы правильно сделать, как отметили Вы, но в реальности делается иначе.
void f() {
int a[100];
for (int i = 0; i < 100; i++)
a[i] = i;
int x = 10;
if (x == 10) {
int b[100];
for (int i = 0; i < 100; i++)
b[i] = i;
}
}void f() {
00EE3C10 push ebp
00EE3C11 mov ebp,esp
00EE3C13 sub esp,414h // выделение памяти на все локальные переменные
00EE3C19 push ebx
00EE3C1A push esi
00EE3C1B push edi
00EE3C1C lea edi,[ebp-414h]
00EE3C22 mov ecx,105h
00EE3C27 mov eax,0CCCCCCCCh
00EE3C2C rep stos dword ptr es:[edi]
int a[100];
for (int i = 0; i < 100; i++)
00EE3C2E mov dword ptr [ebp-1A0h],0
00EE3C38 jmp f+39h (0EE3C49h)
00EE3C3A mov eax,dword ptr [ebp-1A0h]
00EE3C40 add eax,1
00EE3C43 mov dword ptr [ebp-1A0h],eax
00EE3C49 cmp dword ptr [ebp-1A0h],64h
00EE3C50 jge f+57h (0EE3C67h)
a[i] = i;
00EE3C52 mov eax,dword ptr [ebp-1A0h]
00EE3C58 mov ecx,dword ptr [ebp-1A0h]
00EE3C5E mov dword ptr a[eax*4],ecx
00EE3C65 jmp f+2Ah (0EE3C3Ah)
int x = 10;
00EE3C67 mov dword ptr [x],0Ah
if (x == 10) {
00EE3C71 cmp dword ptr [x],0Ah
00EE3C78 jne f+0A3h (0EE3CB3h)
int b[100]; // а здесь ничего не выделяется
for (int i = 0; i < 100; i++)
00EE3C7A mov dword ptr [ebp-350h],0
00EE3C84 jmp f+85h (0EE3C95h)
00EE3C86 mov eax,dword ptr [ebp-350h]
00EE3C8C add eax,1
00EE3C8F mov dword ptr [ebp-350h],eax
00EE3C95 cmp dword ptr [ebp-350h],64h
00EE3C9C jge f+0A3h (0EE3CB3h)
b[i] = i;
00EE3C9E mov eax,dword ptr [ebp-350h]
00EE3CA4 mov ecx,dword ptr [ebp-350h]
00EE3CAA mov dword ptr [ebp+eax*4-344h],ecx
00EE3CB1 jmp f+76h (0EE3C86h)
}
}
00EE3CB3 push edx
00EE3CB4 mov ecx,ebp
00EE3CB6 push eax
00EE3CB7 lea edx,ds:[0EE3CCCh]
00EE3CBD call @_RTC_CheckStackVars@8 (0EE108Ch)
00EE3CC2 pop eax
00EE3CC3 pop edx
00EE3CC4 pop edi
00EE3CC5 pop esi
00EE3CC6 pop ebx
00EE3CC7 mov esp,ebp // а вот здесь освобождение - esp восстанавливается на значение до входа в функцию
00EE3CC9 pop ebp
00EE3CCA retВ остальном вполне согласен.
Здравствуйте, _smit, Вы писали:
Почти все верно
_>
В действительности по крайней мере VC++ так не делает. Память для стека отводится при входе в функцию, хотя переменные, конечно, "логически"перестают существовать при выходе на свою "}". Однако рпмять при этом не освобождается.
"Идейно" было бы правильно сделать, как отметили Вы, но в реальности делается иначе.
В остальном вполне согласен.
Почти все верно
_>
_>void foo()
_>{// выделился фрейм 1 на стеке и вначале фрейма сохранился адрес программного кода куда надо возвратиться при выходе из функции,
_> {// выделился фрейм 2 на стеке
_> int k;
_> int d;
_> } // фрейм 2 освободился на стеке, k и d освободились (разрушились)
_>}// фрейм 1 освободился на стеке, str и b освободились (разрушились)
_>В действительности по крайней мере VC++ так не делает. Память для стека отводится при входе в функцию, хотя переменные, конечно, "логически"перестают существовать при выходе на свою "}". Однако рпмять при этом не освобождается.
"Идейно" было бы правильно сделать, как отметили Вы, но в реальности делается иначе.
void f() {
int a[100];
for (int i = 0; i < 100; i++)
a[i] = i;
int x = 10;
if (x == 10) {
int b[100];
for (int i = 0; i < 100; i++)
b[i] = i;
}
}void f() {
00EE3C10 push ebp
00EE3C11 mov ebp,esp
00EE3C13 sub esp,414h // выделение памяти на все локальные переменные
00EE3C19 push ebx
00EE3C1A push esi
00EE3C1B push edi
00EE3C1C lea edi,[ebp-414h]
00EE3C22 mov ecx,105h
00EE3C27 mov eax,0CCCCCCCCh
00EE3C2C rep stos dword ptr es:[edi]
int a[100];
for (int i = 0; i < 100; i++)
00EE3C2E mov dword ptr [ebp-1A0h],0
00EE3C38 jmp f+39h (0EE3C49h)
00EE3C3A mov eax,dword ptr [ebp-1A0h]
00EE3C40 add eax,1
00EE3C43 mov dword ptr [ebp-1A0h],eax
00EE3C49 cmp dword ptr [ebp-1A0h],64h
00EE3C50 jge f+57h (0EE3C67h)
a[i] = i;
00EE3C52 mov eax,dword ptr [ebp-1A0h]
00EE3C58 mov ecx,dword ptr [ebp-1A0h]
00EE3C5E mov dword ptr a[eax*4],ecx
00EE3C65 jmp f+2Ah (0EE3C3Ah)
int x = 10;
00EE3C67 mov dword ptr [x],0Ah
if (x == 10) {
00EE3C71 cmp dword ptr [x],0Ah
00EE3C78 jne f+0A3h (0EE3CB3h)
int b[100]; // а здесь ничего не выделяется
for (int i = 0; i < 100; i++)
00EE3C7A mov dword ptr [ebp-350h],0
00EE3C84 jmp f+85h (0EE3C95h)
00EE3C86 mov eax,dword ptr [ebp-350h]
00EE3C8C add eax,1
00EE3C8F mov dword ptr [ebp-350h],eax
00EE3C95 cmp dword ptr [ebp-350h],64h
00EE3C9C jge f+0A3h (0EE3CB3h)
b[i] = i;
00EE3C9E mov eax,dword ptr [ebp-350h]
00EE3CA4 mov ecx,dword ptr [ebp-350h]
00EE3CAA mov dword ptr [ebp+eax*4-344h],ecx
00EE3CB1 jmp f+76h (0EE3C86h)
}
}
00EE3CB3 push edx
00EE3CB4 mov ecx,ebp
00EE3CB6 push eax
00EE3CB7 lea edx,ds:[0EE3CCCh]
00EE3CBD call @_RTC_CheckStackVars@8 (0EE108Ch)
00EE3CC2 pop eax
00EE3CC3 pop edx
00EE3CC4 pop edi
00EE3CC5 pop esi
00EE3CC6 pop ebx
00EE3CC7 mov esp,ebp // а вот здесь освобождение - esp восстанавливается на значение до входа в функцию
00EE3CC9 pop ebp
00EE3CCA retВ остальном вполне согласен.