Trwa konkurs "Ogól naczelnego", w którym codziennie możecie wygrać najnowsze maszynki systemowe Hydro Connect 5 marki Wilkinson Sword.

Więcej informacji
Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Wszystko szczelne, czyli wykrywamy wycieki do pamięci w aplikacji C++ w systemach Microsoft Windows

Praca z językiem C/C++ daje spore możliwości w kwestii alokowania pamięci. Niestety, jak to zawsze w życiu bywa, w parze z dużą władzą idzie również spora odpowiedzialność. Najlepszą praktyką unikania błędów jest pisanie kodu, który ich nie zawiera – oczywiście jest to czysty truizm gdyż nie myli się ten kto nic nie robi. Pozostaje więc pytanie: jak żyć z alokowaniem pamięci na stercie?

W systemach GNU/Linuks programista ma do swojej dyspozycji wygodne i popularne narzędzie: Valgrind. Aplikacja ta doczekała się bezpośredniej integracji z QtCreatorem przez co atrakcyjność tego rozwiązania jest, w moich oczach, dość wysoka. Problem pojawia się gdy chcemy wykrywać przecieki do pamięci, na systemie firmy Microsoft. Valgrind jest niestety, projektem na wyłączność dla środowisk Uniksowych. W tym miejscu jako pierwsze rozwiązanie można by zaproponować: użycie Visual Studio z dedykowanym kompilatorem C++ i narzędziami do analizy pamięci. Wiąże się jednak to z pewnymi niedogodnościami. Osobiście preferuje QtCreator ze względu na jego niską konsumpcje pamięci operacyjnej w stosunku do IDE Microsoftu. Oczywiście, z każdą wersją kompilatora, Microsoft sprawa że jego narzędzie jest doskonalsze aczkolwiek niesmak wywołała u mnie informacja że dopiero w wersji 2017, kompilator Visual C++ doczekał się pełnego wsparcia dla standardu C++11/14. Dlatego mimowolnie korzystam z MinGW. Pozostaje więc pytanie, dlaczego nie pozostać przy pracy w środowisku Linuksowym? Odpowiedź jest bardzo prosta: system zarządzania zależnościami wersji bibliotek na pingwinie jest równie ułomny co wsparcie wcześniejszych wersji kompilatora Microsoftu dla standardu C++11/14. Nie kupuje konceptu bibliotek współdzielonych i tyle. Niby można z tym żyć, kombinować ze ściezkami bibliotek itp. ale wydaje mi się że warto poszukać lepszego rozwiązania.

We wcześniejszym akapicie nakreśliłem motywy jakimi kierowałem się przy wyborze narzędzi. Bez odpowiedzi pozostaje w dalszym ciągu pytanie, jak tropić wycieki do pamięci debugując aplikację na Windowsie, wykorzystując do pracy QtCreator/MinGW? Rozwiązaniem naszych problemów będzie Dr.Memory. Jest to w dużym uproszczeniu debuger pamięci dostępny na wszystkich platformach. Na stronie projektu możemy znaleźć wykres dotyczący zysku wydajności jaki przynosi nam korzystanie z Dr.Memory w stosunku do wcześniej wspomnianego Valgrinda. Osobiście nie przeprowadzałem żadnych pomiarów przez co zostaje mi wierzyć (ze stosowną dozą sceptycyzmu) że faktycznie tak jest.

Przykład

Jako że pewne rzeczy najłatwiej zrozumieć na prostym przykładzie, załóżmy że mamy taki kod: struct PersonInfo { int age; std::string name; std::string secondName; }; void createMemoryLeak() { PersonInfo* newPerson = new PersonInfo(); } int main(int argc, char *argv[]) { createMemoryLeak(); createMemoryLeak(); createMemoryLeak(); return 0; }

Oczywiście celowo popełniono w nim zbrodnie nie zawołania operatora delete dla obiektu newPerson. Aby z korzystać z pełni dobrodziejstw programu Dr.Memory, naszą aplikację powinniśmy zbudować w trybie Debug. Mając zbudowany przykład mamy dwie możliwości, pierwsza to przeciągnąć plik wykonywalny .exe na ikonkę Dr.Memory jaka pojawiła się na pulpicie po instalacji aplikacji lub też otworzyć wiersz poleceń i przejść do katalogu gdzie mieści się nasz plik wykonywalny. Proponowałbym zastosować tą drugą opcje ze względu na to że będziemy mieli łatwiejszy dostęp do stosowania flag programu. Będąc w katalogu z naszym plikiem wykonywalnym, wpisujemy do wiersza poleceń komendę:

drmemory.exe ./MemTest.exe

I viola. Stała się magia. Aplikacja domyślnie przy instalacji, "dodaje się" do zmiennych środowiskowych systemu przez co problemów z wywołaniem z terminala, nie powinno być problemów. Przykładowy zrzut ekranu prezentuje poniżej działanie debugera pamięci.

Program wyrzucił nam zarówno w konsoli jak i w postaci pliku tekstowego, raport o tym jakie błędy znalazł. Tak samo jak w przypadku Valgrinda, mamy do dyspozycji informację w których miejscach naszego kodu wystąpił potencjalny problem.

Słowem podsumwania

Wpis był co prawda krótki aczkolwiek myślę że poruszał dość istotną kwestię. Bolączką rozwiązania jest fakt że nie istnieje żadna integracja z wykorzystywanym przeze mnie IDE. W ogólnym rozrachunku, korzystanie z Dr.Memory jest sytuacją Win-Win. Nie uzależniamy się od żadnego systemu operacyjnego czy też kompilatora, dzięki czemu możemy elastycznie krążyć między platformami z zachowaniem pewności że na każdej z nich znajdziemy narzędzie które ułatwi naszą pracę.

Zachęcam do przetestowania samemu powyżej przedstawionego rozwiązania.
 

programowanie hobby

Komentarze

0 nowych
Druedain   14 #1 02.04.2017 19:30

„korzystanie z Dr.Memory jest sytuacją Win-Win. Nie uzależniamy się od żadnego systemu operacyjnego czy też kompilatora”

Jak często zmieniasz kompilatory? A koszt masz taki, że, jak napisałeś, nie masz integracji z IDE. Nie widzę tego jako sytuacja Win-Win.

Autor edytował komentarz w dniu: 02.04.2017 19:31
biomen   8 #2 02.04.2017 19:47

@Druedain
Sytuacja Win-Win jest w tym rozumieniu że mogę elastycznie przełączać się pomiędzy pracą na Windowsie a Linuksie. Dla obu platform mam zestaw odpowiednich narzędzi i żadna z nich, przez to nie jest ułomna.

Wcześniej byłem przygwożdżony do pingwina Valgrindem, teraz dzięki opisanemu narzędziu mam większą swobodę w zmianie środowiska pracy.

Druedain   14 #3 02.04.2017 21:38

@biomen: W tekście wspominasz, że bolączką Dr.Memory jest brak wsparcia dla jakiegokolwiek IDE. Czy żadne z IDE, których używasz nie ma wsparcia dla Valgrinda?

biomen   8 #4 02.04.2017 22:32

@Druedain
"Valgrind. Aplikacja ta doczekała się bezpośredniej integracji z QtCreatorem"

Odpowiedź na twoje pytanie również jest w tekście. IDE którego używam wspiera Valgrinda ale ten jest tylko i wyłącznie na uniksy a z tych, miałem za cel, uciec. Stąd moje zainteresowanie alternatywami.

_qaz7   6 #5 03.04.2017 09:25

Można też skorzystać z detektora leaków z samego runtime'a C/C++ VS-a:

https://msdn.microsoft.com/en-us/library/x98tx3cf.aspx

Zresztą, jak się bardzo mocno uprzesz, możesz przeciążyć wszystkie operatory new i delete, lub w przypadku C owrapować malloca i free i samemu śledzić leaki

Autor edytował komentarz w dniu: 03.04.2017 09:35
czosnek17   7 #6 03.04.2017 19:40

Super :), kiedyś bezskutecznie szukałem takiego czegoś dla Windows. Przyda się na przyszłość.

Autor edytował komentarz w dniu: 03.04.2017 19:41
Kaworu   14 #7 04.04.2017 10:02

@_qaz7: Tylko ten detektor jest powiedzmy takie sobie, bo pokazuje gdzie dokonano alokacji ale nie jaki był callstack. IMO jak coś do VS to, to:

https://vld.codeplex.com/

przemyslaw-rapacz   6 #8 10.04.2017 09:16

Dzięki za program!

  #9 28.04.2017 17:19

Sytuacją win-win jest nieużywanie new i delete w kodzie ;-)

Gratulacje!

znalezione maszynki:

Twój czas:

Ogól Naczelnego!
Znalazłeś(aś) 10 maszynek Wilkinson Sword
oraz ogoliłaś naszego naczelnego!
Przejdź do rankingu
Podpowiedź: Przyciśnij lewy przycisk myszki i poruszaj nią, aby ogolić brodę.