Ostatnia wartość zwracana przez funkcję

2010-01-19 9:23

Debugując program w pracy krokowej w Visual Studio, możemy podglądać wartości wszystkich zmiennych, jakie są dostępne w zasięgu punktu wykonania. Jest to możliwe za pośrednictwem okienka tzw. czujek (watches). Automatycznie wypełnia się ono zmiennymi lokalnymi oraz ewentualnym wskaźnikiem this, pozwalającym podejrzeć wartości pól obiektu, jeśli znajdujemy się akurat w jego metodzie.
Jednak oprócz rzeczywistych zmiennych możemy śledzić też pewne specjalne “pseudozmienne”, udostępniane przez debuger VS. Mają one nazwy zaczynające się od znaku dolara $ i potrafią być bardzo przydatne, co pokażę na przykładzie.

Powiedzmy, że mamy kod składający się z wielu następujących po sobie wywołań funkcji bibliotecznych. Każda z nich zwraca rezultat liczbowy, informujący o (nie)powodzeniu operacji, którego jednak w kodzie nie sprawdzamy – pewnie dlatego, że nie chciało nam się pisać tych wszystkich ifów :) Taka sytuacja może wystąpić chociażby przy ciągu wywołaniach DirectX: ogromna większość funkcji z tej biblioteki zwraca wynik typu HRESULT, który jest liczba zawierającą kod błędu, jeśli takowy wystąpił.
Zauważamy teraz, że ów ciąg wywołań najpewniej zawiera jakiś błąd. Objawem w DX może być chociażby słynne “nic nie widać” :) Jak teraz dojść, które z wielu wywołań zwraca błąd, jeśli w żadnym z nich nie tylko nie sprawdzamy wyniku, ale wręcz w ogóle go nie zapisujemy?…

Podejrzenie wartości EAX w VS

Istnieje na szczęście proste i wygodne rozwiązanie, które nie wymaga żadnych zmian w kodzie. Otóż przy pomocy debugera VS i jego pseudozmiennych możemy podejrzeć wartość rejestrów procesora. Wystarczy użyć symbolu $nazwa_rejestru, jak np. $eax. I właśnie $eax jest tutaj świetnym przykładem, bo rozwiązuje nasz problem. Otóż przez rejestr EAX przekazywany jest zawsze 32-bitowy rezultat zwracany przez każdą porządną funkcję. Przechodząc więc krokowo po naszym kodzie możemy sprawdzić, jak zmienia się ten rejestr po każdym wywołaniu, podglądając w ten sposób wartość, jaką zwróciła w nim funkcja. Wystarczy więc tylko znaleźć to, w którym rezultat informuje o niepowodzeniu… i voila – mamy nasz błąd :)

Tags: , ,
Author: Xion, posted under Programming »


6 comments for post “Ostatnia wartość zwracana przez funkcję”.
  1. Kauach:
    January 19th, 2010 o 10:46

    Bardzo przydatne info =)

  2. yarpen:
    January 19th, 2010 o 13:32

    @ERR,hr rozwiazuje sprawe f-kcji zwracajacych HRESULT.

  3. Xion:
    January 19th, 2010 o 14:38

    Ale $err/@err daje wynik zwracany przez GetLastError, więc to nie jest dokładnie to samo co sam rezultat funkcji. Jasne, dla funkcji WinAPI czy DirectX to nie ma znaczenia, bo one ustawiają ostatni błąd przez SetLastError. W innym przypadku nie musi tak być.

    Na szczęście $eax,hr również działa bez problemu :) (dostaje się wtedy stałe błędów, np. S_OK czy E_OUTOFMEMORY).

  4. Mic43:
    January 20th, 2010 o 14:10

    Szkoda tylko, że działa tylko w unmanaged:(

  5. Reg:
    January 24th, 2010 o 15:18

    Podczas debugowania w VC okienko Autos zawiera (czasami…) rezultat, jaki zwróciła ostatnio wywołana funkcja, zatytułowany “nazwafunkcji returned”.

  6. Xion:
    January 24th, 2010 o 17:35

    @Reg: Tak, ale no właśnie tylko czasami :) Nie udało mi się dojść, kiedy tak się dzieje i dlaczego, i m.in. w tego powodu spróbowałem znaleźć inny sposób na uzyskanie tej informacji.

    @Mic43: W kodzie managed błędy zwykle wiążą się z wyjątkami, a te można podejrzeć w debugerze za pomocą $exception.

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.