Narzędzia wspomagające programowanie w językach C/C++ dla systemu Linux. Autor: Adam Stolcenburg

Podobne dokumenty
Wprowadzenie do Valgrinda

Wykład 2

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

Narzędzia do oceny wydajności kodu. Narzędzia do oceny wydajności kodu 1/32

Automatyzacja kompilacji. Automatyzacja kompilacji 1/40

GNU GProf i GCov. przygotował: Krzysztof Jurczuk Politechnika Białostocka Wydział Informatyki Katedra Oprogramowania ul. Wiejska 45A Białystok

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

C++ język nie dla ludzi o słabych nerwach. Małgorzata Bieńkowska

PROGRAMOWANIE w C prolog

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Piotr Dwieczkowski. Code coverage. Mierzenie pokrycia kodu, teoria oraz praktyka w C/C++

Wstęp do programowania

Automatyzacja kompilacji. Automatyzacja kompilacji 1/28

Programowanie Proceduralne

CODE::BLOCKS & VALGRIND OPRACOWAŁ MICHAŁ BETHKE

Programowanie Proceduralne

Pobieranie argumentów wiersza polecenia

Wprowadzenie do szablonów klas

Tworzenie oprogramowania

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Systemy Operacyjne. Ćwiczenia

Sposoby wykrywania i usuwania błędów. Tomasz Borzyszkowski

Programowanie I. O czym będziemy mówili. Plan wykładu nieco dokładniej. Plan wykładu z lotu ptaka. Podstawy programowania w językach. Uwaga!

Programowanie Systemów Wbudowanych

Make jest programem komputerowym automatyzującym proces kompilacji programów, na które składa się wiele zależnych od siebie plików.

Podstawy programowania. Wykład 9 Preprocesor i modularna struktura programów. Krzysztof Banaś Podstawy programowania 1

Podstawy Informatyki Wprowadzenie do języka C dr inż. Jarosław Bułat

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 8. Karol Tarnowski A-1 p.

Tworzenie oprogramowania

Informatyka. Wy-03 Dynamiczna alokacja pamięci, wyjątki. mgr inż. Krzysztof Kołodziejczyk

Dzisiejszy wykład. Klasa string. wersja prosta wersja ze zliczaniem odwołań. Wyjątki Specyfikator volatile Semafory

TESTOWAĆ TESTOWAĆ TESTOWAĆ TESTOWAĆ TESTOWAĆ TESTOWAĆ TESTOWAĆ

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Programowanie w C++ Wykład 10. Katarzyna Grzelak. 21 maja K.Grzelak (Wykład 10) Programowanie w C++ 1 / 21

Laboratorium Informatyka (I) AiR Ćwiczenia z debugowania

Zaawansowane programowanie w języku C++ Zarządzanie pamięcią w C++

Programowanie w języku C++

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

dynamiczny przydział pamięci calloc() memset() memcpy( ) (wskaźniki!! )

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

DYNAMICZNE PRZYDZIELANIE PAMIECI

Kompilacja i scalanie programów w linii poleceń gcc i make

Wykład 1

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

Środowisko Keil. Spis treści. Krzysztof Świentek. Systemy wbudowane. 1 Trochę teorii. 2 Keil

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Microsoft IT Academy kurs programowania

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Uzupełnienie dot. przekazywania argumentów

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

MS Visual Studio 2005 Team Suite - Performance Tool

Tablice w argumentach funkcji. Tablicy nie są przekazywane po wartości Tablicy są przekazywane przez referencje lub po wskaźniku

Szablony funkcji i szablony klas

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Wprowadzenie. Programowanie Obiektowe Mateusz Cicheński

Modelowanie numeryczne w fizyce atmosfery Ćwiczenia 3

Fragment wykładu z języka C ( )

Kompilator języka C na procesor 8051 RC51 implementacja

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

PARADYGMATY PROGRAMOWANIA Wykład 4

Zaawansowane programowanie w języku C++ Klasy w C++

Wykład 12. Programowanie serwera MS SQL 2005 w C#

Inżynieria Wytwarzania Systemów Wbudowanych

Programowanie mikrokontrolerów AVR

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Grzegorz Cygan. Wstęp do programowania mikrosterowników w języku C

Co nie powinno być umieszczane w plikach nagłówkowych:

Informatyka. Wy-02 Tablice, wskaźniki, warunki i pętle. mgr inż. Krzysztof Kołodziejczyk

Automatyczne generowanie testów z modeli. Bogdan Bereza Automatyczne generowanie testów z modeli

Programowanie proceduralne INP001210WL rok akademicki 2017/18 semestr letni. Wykład 7. Karol Tarnowski A-1 p.

Zadania: 1. Funkcja przeliczająca F na C: float FtoC(float f){ return (f 32.0) * 5.0 / 9.0; }

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Wskaźniki. Programowanie Proceduralne 1

Instrukcja instalacji winbgim

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Programowanie obiektowe zastosowanie języka Java SE

Obsługa wyjątków. Język C++ WW12

Wstęp. #define include include include include include include

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Zaawansowane programowanie w C++ (PCP)

Wyjątki. Wyjątki. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Politechnika Wrocławska

KONSTRUKCJA KOMPILATORÓW

FUNKCJE WZORCOWE. Wykład 10. Programowanie Obiektowe (język C++) Funkcje wzorcowe wprowadzenie (2) Funkcje wzorcowe wprowadzenie (1)

Wstęp do programowania

Zajęcia nr 1 Podstawy programowania. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Zmienne, stałe i operatory

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Wprowadzenie do biblioteki klas C++

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Wskaźniki. Informatyka

Sieciowa komunikacja procesów - XDR i RPC

Transkrypt:

Narzędzia wspomagające programowanie w językach C/C++ dla systemu Linux Autor: Adam Stolcenburg

Kompilatory gcc GNU Compiler Collection (dawniej GNU C Compiler) https://gcc.gnu.org/ Projekt GNU GNU GPL 3+ with GCC Runtime Library Exception pierwsza wersja udostępniona 22 marca 1987 roku najnowsza stabilna wersja 6.2 z 22 sierpnia 2016 clang http://clang.llvm.org/ Apple, Microsoft, Google, ARM, Intel, AMD University of Illinois/NCSA Open Source License pierwsza wersja udostępniona 11 lipca 2007 najnowsza stabilna wersja 3.9.0 z 2 września 2016 page 2

Jak używać kompilatorów gcc source.cpp o binary generowanie finalnego pliku wykonywalnego: -o generowanie pośrednich plików binarnych: -c definicja poziomu optymalizacji: -O0, -O1, -O2, -Os, -03 dodanie informacji debugowych: -ggdb definicja poziomu ostrzeżeń clang włączenie wszystkich ostrzeżeń: -Weverything gcc przykładowe opcje włączające ostrzeżenia: -pedantic -Wall -Wextra -Wcastalign -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winitself -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Woldstyle-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef wyłączanie wybranych ostrzeżeń: -Wno- mnóstwo innych opcji opisanych na stronach elektronicznego podręcznika: man gcc, man clang http://stackoverflow.com/questions/5088460/flags-to-enable-thorough-and-verbose-g-warnings page 3

Błędy kompilacji class MyClass { ; void test(myclass* my_class_ptr) { MyClass my_class = my_class_ptr; gcc error.cpp: In function void test(myclass*) : error.cpp:3:22: error: conversion from MyClass* to non scalar type MyClass requested MyClass my_class = my_class_ptr; ^ clang error.cpp:3:11: error: no viable conversion from 'MyClass *' to 'MyClass' MyClass my_class = my_class_ptr; ^ ~~~~~~~~~~~~ error.cpp:1:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'MyClass *' to 'const MyClass &' for 1st argument; dereference the argument with * class MyClass { ; ^ 1 error generated. page 4

Ostrzeżenia void test(int end) { for (unsigned int i = 0; i < end; ++i) { gcc warning.cpp: In function void test(int) : warning.cpp:2:32: warning: comparison between signed and unsigned integer expressions [ Wsigncompare] for (unsigned int i = 0; i < end; ++i) { ^ clang warning.cpp:2:30: warning: comparison of integers of different signs: 'unsigned int' and 'int' [ Wsign compare] for (unsigned int i = 0; i < end; ++i) { 1 warning generated. ~ ^ ~~~ page 5

Makra ułatwiające debugowanie FUNCTION - nazwa aktualnej funkcji PRETTY_FUNCTION - nazwa aktualnej funkcji wraz zakresem, parametrami i zwracaną wartością LINE - linia w pliku źródłowym FILE - nazwa pliku źródłowego #include <cstdio> struct Test { static void print() { printf("%s\n%s\n%s %d\n", FUNCTION, PRETTY_FUNCTION, FILE, LINE ); ; int main() { Test::print(); return 0; wynik działania print static void Test::print() macros.cpp 4 page 6

Make (1) narzędzie służące do automatyzacji procesu budowania plików wykonywalnych i bibliotek z plików źródłowych pierwsza wersja z 1977 roku GNU make - https://www.gnu.org/software/make/ opis procesu budowania opisany w plikach makefile przepisy składające się z celów oraz listy zależności polecenia dla celów uruchamiane jeśli czas modyfikacji plików z listy zależności jest późniejszy niż czas modyfikacji celu polecenia budujące cel na podstawie listy zależności definiowane poniżej listy zależności w liniach rozpoczynających się od znaku tabulacji target: target.cpp g++ target.cpp o target możliwość wyboru celu z linii poleceń make target page 7

Make (2) definicja celów za pomocą wzorców dopasowania %.o: %.cpp g++ $< c parametryzowanie za pomocą zmiennych %.o: %.cpp $(CXX) $< c możliwość ustawienia zmiennych z lini poleceń make CXX=clang target.o obsługa rozgałęzień ifeq ($(RELEASE),1) CXXFLAGS= O3 else CXXFLAGS= ggdb O0 endif obsługa wbudowanych funkcji: https://www.gnu.org/software/make/manual/html_node/functions.html SOURCES=$(wildcard *.cpp) OBJECTS=$(patsubst %.cpp,%.o,$(sources)) page 8

Make przykładowy plik makefile SOURCES=$(wildcard *.cpp) OBJECTS=$(patsubst %.cpp,%.o,$(sources)) BINARY=example ifeq ($(RELEASE),1) CXXFLAGS= O3 else CXXFLAGS= ggdb O0 Wall endif all: $(BINARY) $(BINARY): $(OBJECTS) $(CXX) $^ o $@ %.o: %.cpp $(CXX) $(CXXFLAGS) $< c clean: rm f $(BINARY) $(OBJECTS) page 9

KDevelop https://www.kdevelop.org/ nowoczesne, darmowe zintegrowane środowisko programistyczne napisane w C++ rozumie C++ zaawansowany system auto-uzupełniania podświetlanie zmiennych na podstawie zakresu ich widoczności wygodna nawigacja między funkcjami łatwa integracja z zewnętrznymi systemami budowania make, cmake, qmake brak wbudowanego kompilatora obsługa debuggera gdb automatyczne formatowanie wsparcie dla refaktoryzacji wizualizacja hierarchii class integracja z systemami kontroli wersji wbudowane wsparcie dla Doxygena sprawdzanie pisowni wewnątrz komentarzy i literałów page 10

Cppcheck http://cppcheck.sourceforge.net/ narzędzie służące do statycznej analizy kodu nacisk na unikanie tzw. false positives wykrywa następujące rodzaje błędów: dostęp poza obszarem zaalokowanej pamięci wycieki pamięci dereferencje wskaźnika null dostęp do niezainicjalizowanych zmiennych nieprawidłowe użycie biblioteki STL nieużywany oraz nadmiarowy kod i wiele innych: http://sourceforge.net/p/cppcheck/wiki/listofchecks bezproblemowe użycie cppcheck enable=style,performance,portability <nazwa pliku/katalogu> page 11

Cppcheck przykładowe błędne kody bug1.cpp void test() { char tab[10]; for (int i = 0; i <= 10; ++i) { tab[i] = 0; bug2.cpp class Base { ; class Derived : public Base { const char* m_ptr; public: Derived() : m_ptr(new char) { ~Derived() { delete m_ptr; ; void test() { Base* base_ptr = new Derived(); delete base_ptr; page 12

Cppcheck rezultat działania cppcheck bug1.cpp Checking bug1.cpp... [bug1.cpp:4]: (error) Buffer is accessed out of bounds: tab cppcheck bug2.cpp Checking bug2.cpp... [bug2.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor. page 13

Clang static analyzer http://clang-analyzer.llvm.org/ narzędzie służące do statycznej analizy kodu część projektu clang zaawansowane algorytmy wnioskowania możliwość sprawdzenia pojedynczego pliku scan build g++ code.cpp c możliwość sprawdzenia całego projektu bazującego na przykład na make, w czasie analizy ustawiane są między innymi zmienne środowiskowe CC i CXX scan build make all wizualizacja raportu ze szczegółowym opisem przepływu sterowania page 14

Clang static analyzer błędny kod int* get_greater_than_zero_or_null(int value, bool force_zero) { int* result_ptr = 0; if (value > 0) result_ptr = new int(value); if (force_zero) *result_ptr = 0; return result_ptr; page 15

Clang static analyzer przykładowy raport page 16

lcov http://ltp.sourceforge.net/coverage/lcov.php narzędzie wizualizujące pokrycie kodu wygenerowane przez gcov gcov standardowe narzędzie wchodzące w skład GCC współpracuje zarówno z GCC jak i clang możliwość łączenia raportów z wykonań wielu plików wykonywalnych wymaga kompilacji i linkowania kodu z opcją coverage (generuje.gcno) g++ coverage c code.cpp o code oraz uruchomienia (generuje.gcda)./code raport z plików.gcno oraz.gcda jest generowany za pomocą lcov capture rc lcov_branch_coverage=1 directory=. o cov.info genhtml legend rc lcov_branch_coverage=1 cov.info o output page 17

lcov przykładowy raport page 18

Valgrind http://valgrind.org/ zbiór narzędzi służących do dynamicznej analizy kodu memcheck wykrywanie problemów związanych z niewłaściwym użyciem pamięci cachegrind profilowanie użycia cache callgrind cachegrind + grafy wywołań, profilowanie kodu massif monitorowanie użycia pamięci przez poszczególne cześci kodu helgrind, DRD wykrywanie problemów związanych z wątkami uruchamiany na pliku wykonywalnym zalecane ustawienia opcji kompilacji -ggdb -O0 wymaga uruchomienia analizowanego fragmentu kodu page 19

Valgrind (memcheck) wykrywanie błędów związanych z niewłaściwym użyciem pamięci wycieki pamięci dostęp do złych obszarów pamięci (niezaalkowanych, zwolnionych itd.) użycie niezainicjalizowanych zmiennych niewłaściwe zwolnienie pamięci (wielokrotne, za pomocą złych funkcji) spowolnienie działania kodu od 10 do 30 razy domyślne narzędzie valgrinda, sposób uruchamiania valgrind./a.out opcje ułatwiające wykrycie wycieków pamięci valgrind leak check=full./a.out opcje ułatwiające znalezienie źródeł niezainicjalizowanych obszarów pamięci valgrind track origins=yes./a.out page 20

Valgrind (memcheck) raport ==28815== Memcheck, a memory error detector ==28815== Copyright (C) 2002 2013, and GNU GPL'd, by Julian Seward et al. ==28815== Using Valgrind 3.10.0.SVN and LibVEX; rerun with h for copyright info ==28815== Command:./a.out ==28815== ==28815== ==28815== HEAP SUMMARY: ==28815== in use at exit: 10 bytes in 1 blocks ==28815== total heap usage: 2 allocs, 1 frees, 18 bytes allocated ==28815== ==28815== LEAK SUMMARY: ==28815== definitely lost: 10 bytes in 1 blocks ==28815== indirectly lost: 0 bytes in 0 blocks ==28815== possibly lost: 0 bytes in 0 blocks ==28815== still reachable: 0 bytes in 0 blocks ==28815== suppressed: 0 bytes in 0 blocks ==28815== Rerun with leak check=full to see details of leaked memory ==28815== ==28815== For counts of detected and suppressed errors, rerun with: v ==28815== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) page 21

Valgrind (memcheck) wyciek pamięci #include <stdlib.h> typedef struct { char* data_ptr; buffer_t; buffer_t* get_buffer(int size) { buffer_t* result_ptr = (buffer_t*)malloc(sizeof(buffer_t)); result_ptr >data_ptr = (char*)malloc(size * sizeof(char)); return result_ptr; void test_leak() { buffer_t* buffer_ptr = get_buffer(10); free(buffer_ptr); int main() { test_leak(); return 0; page 22

Valgrind (memcheck) raport wycieku pamięci ==28976== HEAP SUMMARY: ==28976== in use at exit: 10 bytes in 1 blocks ==28976== total heap usage: 2 allocs, 1 frees, 18 bytes allocated ==28976== ==28976== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==28976== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck amd64 linux.so) ==28976== by 0x4005A2: get_buffer (memory_leak.c:9) ==28976== by 0x4005C4: test_leak (memory_leak.c:14) ==28976== by 0x4005E4: main (memory_leak.c:19) page 23

Valgrind (memcheck) niezainicjalizowana zmienna #include <cstdio> static int counter = 0, sum = 0; void increment(int i) { sum += i; void call30increment() { for (int i = 0; i < 30; ++i) { increment(++counter); void call100increment() { int counter; for (int i = 0; i < 100; ++i) { increment(++counter); int main() { call30increment(); call100increment(); printf("%d\n", sum); return 0; page 24

Valgrind (memcheck) raport niezainicjalizowanej zmiennej ==29191== Conditional jump or move depends on uninitialised value(s) ==29191== at 0x4E8158E: vfprintf (vfprintf.c:1660) ==29191== by 0x4E8B498: printf (printf.c:33) ==29191== by 0x4005CF: main (uninitialized.cpp:16) ==29191== Uninitialised value was created by a stack allocation ==29191== at 0x400580: call100increment() (uninitialized.cpp:8) page 25

Valgrind (callgrind) profilowanie czasu wykonania kodu spowolnienie działania kodu od 20 do 100 razy sposób uruchamiania valgrind tool=callgrind./a.out możliwość kontroli w czasie działania za pomocą narzędzia callgrind_control -i on włączenie profilowania; -i off wyłączenie profilowania; -z zerowanie statystyk raport domyślnie generowany do pliku: callgrind.out.<pid> możliwość wizualizacji raportu za pomocą kcachegrind page 26

Valgrind (callgrind) profilowany kod #include <pthread.h> #include <stdio.h> static int counter = 0, sum = 0; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void increment(int i) { sum += i; void call30increment() { pthread_mutex_lock(&mutex); for (int i = 0; i < 30; ++i) { increment(++counter); pthread_mutex_unlock(&mutex); void call100increment() { for (int i = 0; i < 100; ++i) { pthread_mutex_lock(&mutex); increment(++counter); pthread_mutex_unlock(&mutex); int main() { call30increment(); call100increment(); printf("%d\n", sum); return 0; page 27

kcachegrind wizualizacja grafu wywołań page 28

Dziękuję