On 07/19/2015 12:31 AM, Marcin Cieslak wrote:
Rozpisałem Ci to na dwa błędu na Githubie. Robisz m.in. coś nie tak w dektruktorze swojej maszyny wirtualnej.
Testy też mogłyby wykrywać core dump, tak przy okazji (nie wiedziałem, czy core powstał z jednego testu - okazało się, że każda z czterech awarii coś zrzuca).
Tego błędu nie mogę od dosyć dawna trafić. Na jedynym sprzęcie, na którym udało mi się go wywołać pojawia się "losowo", ale będę szukać dalej skoro ktoś jeszcze trafił. Czy przypadkiem nie uruchamiasz testów na i7? Myślałem kiedyś, że może to kwestia podwójnego zwalniania jakiejś pamięci, ale nie wydaje mi się. W planach mam napisanie areny pamięci (nie jestem pewien czy po polsku tak będzie "memory arena") i używanie "placement new" wszędzie. Wtedy będę mógł dokładnie prześledzić co i kiedy się alokuje, zwalnia itd. Może pomoże.
Szkoda, ja do dziś nie wiem jak się po polsku odmienia Lua (d:Luji,c:Luje,b:Luję?:) czy może jak "Lła"?
Ja po prostu nie odmieniam ;-) Podobnie jak IKEA.
Przy okazji pytanie, bo akurat siedzę teraz trochę w obsłudze wyjątków w C++ i w CoreCLR (open source .NET):
Jak rozwiązałeś problem "rozwijania stosu" - przywracania kontekstu miejsca, w którym łapiesz wyjątek?
~Marcin
Cwaniactwem. Maszyna ma tak naprawdę dwa stosy zamiast tylko jednego. Pierwszy jest zwykłym stosem wywołań funkcji, drugi stosem "wyłapywaczy".
Każdy wyłapywacz ma przypisaną ramkę ze stosu funkcji, oraz listę typów, które potrafi złapać. Kiedy rzucam wyjątek maszyna rejestruje go, i iteruje w górę stosu wyłapywaczy w poszukiwaniu wyłapywacza, który potrafi obsłużyć typ rzuconego obiektu (na tym etapie w ogóle nie ruszam stosu funkcji). Możliwe są dwa wyniki: albo jakiś wyłapywacz ma zarejestrowaną obsługę danego typu, albo skończy się stos wyłapywaczy.
Jeśli żaden wyłapywacz nie jest w stanie obsłużyć rzuconego obiektu następuje przerwanie działania programu. W takim wypadku nastąpi wygenerowanie informacji o fakcie, że nie udało się złapać rzuconego obiektu (informacja zawiera typ i wartość niewyłapanego obiektu, stack trace, stan rejestrów w ostatniej ramce oraz stan licznika instrukcji).
Jeśli któryś wyłapywacz jest w stanie obsłużyć rzucony obiekt, maszyna zaczyna modyfikować stos wywołań (można to zrobić, bo skoro wyjątek został obsłużony to istniejąca historia wywołań nie będzie potrzeba do wygenerowania stack trace). W tym celu CPU pobiera adres ramki na stosie wywołań dla której został zarejestrowany wyłapywacz, i tak długo usuwa ramki ze stosu, aż nie trafi na "tą jedyną". Kiedy już ją znajdzie, ustawia zestawy rejestów na znajdujące się w tej ramce i wznawia działanie od adresu instrukcji, pod którym znajduje się blok obsługujący dany typ wyjątku.