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.

r   e   k   l   a   m   a

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