GUT Intel 2015/16 1/30 Inżynieria Wytwarzania Systemów Wbudowanych Wykład 3 Iwona Kochańska Katedra Systemów Elektroniki Morskiej WETI PG October 18, 2018
Dobre praktyki GUT Intel 2015/16 2/30
Przenośność (Portability) Przenośność (portability) - wysiłek, który może być wymagany dla przeniesienia oprogramowania z jednego systemu sprzętowego lub programowego do drugiego Dobra praktyka: pisz w takim stylu, który jest niezależny od konkretnego kompilatora używaj tylko standardowych elementów języka używaj tylko standardowych znaków i znaków specjalnych upewniaj się co do reprezentacji typów danych w systemie i zapisuj to w dokumentacji pisz w stylu niezależnym od środowiska, w którym wytwarzasz oprogramowanie wszystkie elementy zależne od implementacji powinny być udokumentowane, np.: reprezentacja liczb zmiennoprzecinkowych jak traktowane sa znaki reszty z dzielenia liczb całkowitych (C90) kolejność szukania plików wymienionych przez dyrektywy #include użycie innych znaków niż standardowe (alfanumeryczne łacińskie, _ { } [ ] # ( ) < > % : ;.? * + / ^ & =,, spacja, znaki nowej linii i GUT Intel 2015/16 3/30 powrotu karetki, tab)
Przenośność (Portability) Znaki modyfikacji (ucieczki), sekencja zmodyfikowana (znak modyfikacji + sekwencja po nim następujaca, której domyślne znaczenie zmienił znak modyfikacji) Standardowe znaki modyfikacji: Nie używaj innych niż standardowe znaków modyfikacji! GUT Intel 2015/16 4/30
Przenośność (Portability) Typ char a znak (signed/unsigned) w przeciwieństwie do typu int typ char nie ma domyślnie okreslonego znaku - to zależy od kompilatora. jesli chcesz wykorzytać char do przechowywania wartości liczbowej, określaj jawnie, czy jest to signed char czy unsigned char, najlepiej tworzac nowa definicję typu GUT Intel 2015/16 5/30
Przenośność (Portability) Wartości typu enum w języku C typ wyliczeniowy powinien reprezentować wartości int Język C++ pozwala na wartości long int w typie wyliczeniowym GUT Intel 2015/16 6/30
Przenośność (Portability) Pojedyncze bity nie używaj pojedynczych bitów (bit fields) jesli już musisz użyć pojedynczych bitów, rób to w sposób taki, by pozycja bitu w słowie nie miała znaczenia. Używaj masek bitowych i operatorów & i Różnice w interpretacji pojedynczych bitów w słowie moga wynikać z: 1. Różnicy między typem signed a unsigned 2. Kolejności bitów w słowie 3. Rzeczywistej reprezentacji pola bitowego w jednostce pamięci GUT Intel 2015/16 7/30
Przenośność (Portability) Format #include niektóre kompilatory zrozumieja format #include inny niż z użyciem i <>, ale większość zgłosi bład. Unikaj innych rozwiazań niz standardowe i <>. typu GUT Intel 2015/16 8/30
Przenośność (Portability) Format #include używaj < > dla plików nagłówkowych dostarczanych wraz z kompilatorem używaj dla plików nagłówkowych innych niż dostarczanych wraz z kompilatorem GUT Intel 2015/16 9/30
Przenośność (Portability) Format #include Standard języka C nie definiuje, jak interpretować znaki \ lub /* w łańcuchu znaków ograniczonym przez < > lub Zachowanie znaku : jest również specyficzne dla kompilatora GUT Intel 2015/16 10/30
Przenośność (Portability) Format #include Nigdy nie podawaj bezwzględnej ścieżki do pliku nagłówkowego GUT Intel 2015/16 11/30
Przenośność (Portability) Kod assemblera w kodzie C/C++ Nie wszystkie kompilatory obsługuja funkcję asm (string),która pozwala na dołaczenie do kodu instrukcji assemblera. Lepiej jest używać funkcji inline zdefiniowanej jako makro preprocesora GUT Intel 2015/16 12/30
Przenośność (Portability) Dyrektywy #pragma - funkcje specyficzne dla kompilatora Dyrektywy pragma umożliwiaja definiowanie funkcji specyficznych dla kompilatora Nie wołaj takich specyficznych funkcji bezpośrednio - definiuj dla nich makra GUT Intel 2015/16 13/30
Przenośność (Portability) Typy proste Rozmiar i reprezentacja prostych typów (int i floating point) zależa od kompilatora Definiuj własne typy, nawet dla typów prostych Standard C99 proponuje następuj ace nazwy (jeśli używasz C90, użyj tych nazw do zdefiniowania typów prostych): GUT Intel 2015/16 14/30
Dobre praktyki Wydajność (efficiency) - ilość przetwarzanych zasobów i kodu, które program potrzebuje do wykonywania swoich funkcji Pisz tak, by brać pod uwagę ilość zasobów i wymagania czasowe wobec działania progrmu GUT Intel 2015/16 15/30
Wydajność Wywołanie funkcji a makro Częste wywołania funkcji moga spowalniać działanie systemu Zadania krytyczne czasowo moga być realizowane przez makra, ale z zachowaniem szczególnej ostrożności - działanie makr zależy od implementacji Liczne wywołania makr zwiększaja rozmiar pliku binarnego GUT Intel 2015/16 16/30
Przenośność (Portability) Niezmienne elementy w instrukcjach iteracyjnych Nie umieszczaj w instrukcjach iteracyjnych elementów, które sa niezmienne Kompilator w procesie optymalizacji nie musi zoptymalizować wszystkiego. Wówczas taka stała instrukcja wołana iteracyjnie spowalnia działanie systemu. GUT Intel 2015/16 17/30
Wydajność Wskaźniki do struktur danych Nie przekazuj do funkcji całych struktur danych, tylko wskaźniki do nich GUT Intel 2015/16 18/30
Typowe błędy w oprogramowaniu systemów wbudowanych Instrukcje bez znaczenia dla działania programu moga prowadzić do błędnego rozumienia kodu instrukcja, która nigdy nie jest wykonywana return ret ; ret = ERROR ; instrukcja, której rezultat nigdy nie jest wykorzystany void func ( ) { int cnt ; } cnt = 0; return ; GUT Intel 2015/16 19/30
Typowe błędy w oprogramowaniu systemów wbudowanych Instrukcje bez znaczenia dla działania programu moga prowadzić do błędnego rozumienia kodu instrukcja, której rezultat nigdy nie jest wykorzystany int func ( ) { int cnt ; } return cnt ++; parametry do funkcji, które nigdy nie sa wykorzystane int func ( int in) { in = 0; /* Overwriting the parameter */ } GUT Intel 2015/16 20/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne wyrażenia i instrukcje błędne sprawdzanie, czy zmienna mieści się w zakresie wartości (w języku C poniższe wyrażenie zawsze reprezentuje wartość TRUE) if (0 < x < 10) porównanie zmiennej z wartościa poza zakresem zmiennej unsigned char uc; unsigned int ui; if ( uc == 256) switch (uc) { case 256: } if (ui < 0) GUT Intel 2015/16 21/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne wyrażenia i instrukcje porównywanie łańcuchów znaków za pomoca operatora == if ( str == " abc ") niezgodność między typem zwracanym przez funkcję a zwracana wartościa int func1 ( int in) { if (in < 0) return ; /* No good */ return in ; } GUT Intel 2015/16 22/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne odwołanie do pamięci odwołanie do pamięci poza zakresem tablicy char var1 [N]; for (i = 1; i <= N; i ++) { /* Accessing outside the array bounds */ var1 [i] = i; } var1 [ -1] = 0; /* error */ var1 [N] = 0; /* error */ GUT Intel 2015/16 23/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne odwołanie do pamięci Referencja do zmiennej lokalnej po wyjściu z funkcji int * func ( tag *p) { int x; /* The automatic variable memory area is referenced after the function return */ p-> mem = &x; return &x; } tag y; int *p; p = func (&y); *p = 10; *y. mem = 20; GUT Intel 2015/16 24/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne odwołanie do pamięci Referencja do pamięci, która została zwolniona struct stag { /* A list structure */ struct stag * next ;... }; struct stag * wkp ; /* Pointer to the list structure */ struct stag * top ; /* Start pointer to the list structure */... /* Process to free the list structure by its elements */ /* It will accesses to an already freed area at the third control expression in the for statement */ for ( wkp = top ; wkp!= NULL ; wkp = wkp -> next ) { free ( wkp ); } GUT Intel 2015/16 25/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne odwołanie do pamięci błędny rozmiar kopiowanego obszaru pamięci # define A 10 # define B 20 char char a[a]; b[b]; memcpy (a, b, sizeof (b )); GUT Intel 2015/16 26/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne wyrażenia logiczne użycie && zamiast if (x < 0 && x > 10) użycie zamiast && int i, data [10], end = 0; for (i = 0; i < 10! end ; i ++) { data [i] = Value_assigned ; /* risk of corrupting outside the ar if ( termination_condition ) { end = 1; } } Określaj ac warunek wykonania referencji do pamięci zawsze używaj operatora &&! GUT Intel 2015/16 27/30
Typowe błędy w oprogramowaniu systemów wbudowanych Niepoprawne wyrażenia logiczne użycie operatora bitowego zamiast logicznego if ( len1 & len2 ) Mylenie operatorów = i == if ( x = 0 ) GUT Intel 2015/16 28/30
Typowe błędy w oprogramowaniu systemów wbudowanych Używanie tej samej nazwy makra dla różnych definicji # define AAA 100 a = AAA ; # define AAA 10 b = AAA ; Zapis do pamięci oznaczonej jako const void func ( const int *p) { *p = 0; /* Writing into the const area ( error ) */ Nie każdy kompilator zgłosi bład! GUT Intel 2015/16 29/30
Literatura GUT Intel 2015/16 30/30