W poniższym kodzie funkcja foo
wywołuje się rekurencyjnie jeden raz. Wewnętrzne wywołanie powoduje naruszenie prawa dostępu. Zewnętrzne wywołanie wychwytuje wyjątek.Czy __finally ma działać po EXCEPTION_CONTINUE_SEARCH?
#include <windows.h>
#include <stdio.h>
void foo(int cont)
{
__try
{
__try
{
__try
{
if (!cont)
*(int *)0 = 0;
foo(cont - 1);
}
__finally
{
printf("inner finally %d\n", cont);
}
}
__except (!cont? EXCEPTION_CONTINUE_SEARCH: EXCEPTION_EXECUTE_HANDLER)
{
printf("except %d\n", cont);
}
}
__finally
{
printf("outer finally %d\n", cont);
}
}
int main()
{
__try
{
foo(1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("main\n");
}
return 0;
}
oczekiwany wynik tutaj powinno być
inner finally 0
outer finally 0
inner finally 1
except 1
outer finally 1
Jednak outer finally 0
jest widoczny brakuje realnej produkcji. Czy to błąd, czy jest jakiś szczegół, który przeoczyłem?
Dla kompletności, dzieje się z VS2015, kompilacja dla x64. Zaskakująco nie dzieje się to na x86, co prowadzi mnie do przekonania, że to naprawdę błąd.
Może to technicznie należeć do zakresu niezdefiniowanych zachowań, jak przypisujesz wskaźnik zerowy. Czy próbowałeś rzucić zwykły wyjątek za pomocą 'RaiseException'? – OmnipotentEntity
Cóż, nie dobrze. To nie jest nowy problem, VS2013 zachowuje się w ten sam sposób. Wygląda jak ograniczenie strukturalne/SAFESEH do mnie, specyficzne dla rekurencji, działa dobrze w przypadku nierekurencyjnym. Bardzo wątpliwe, czy ktoś tutaj może rozwiązać ten problem, najlepiej o ping connect.microsoft.com o tym. –
@OmnipotentEntity: Przypisywanie do wskaźnika pustego jest * niezdefiniowanym zachowaniem *, jeśli chodzi o standard języka C++. Jednak na platformie Windows jest to dobrze zdefiniowane: instrukcja powoduje naruszenie zasad dostępu, które jest przekazywane do kodu użytkownika przez wyjątek SEH. – IInspectable