Cum se pot evita bug-urile tipice încorporate


Înțelegerea erorilor software și hardware prin exemplul altor sisteme încorporate vă poate ajuta să identificați, să diagnosticați și să remediați erorile din propriul sistem.







În ciuda faptului că niciuna dintre aceste erori nu a cauzat un prejudiciu grav, toate ilustrează caracteristici curioase. În cursul narațiunii, vom analiza unele dintre caracteristicile operației preprocesorului C și voi da câteva avertismente legate de utilizarea temporizatorilor.

Primul grup de erori provoacă modificări care nu ar trebui să afecteze sistemul în nici un fel, dar se întâmplă într-un mod incomprehensibil. Opțiunile diferite de optimizare nu ar trebui să afecteze comportamentul sistemului din punct de vedere al funcționării, ci afectează doar viteza de execuție a codului și dimensiunea sa. Desigur, atunci când un sistem care rulează în timp real începe să execute rapid anumite fragmente de cod, poate apărea o condiție de semnal de semnal, dar există și alte efecte neclară ale optimizării care vă pot aduce într-o mizerie.

Într-un caz, colegii mei și cu mine am găsit o eroare în cod, care nu era în versiunea anterioară. Am studiat istoricul modificărilor de la versiunea anterioară la versiunea curentă și am restrâns căutarea la această opțiune de compilator. Un studiu mai detaliat al codului a arătat că, din cauza muncii inexacte, am devenit neprotejată înainte de influența optimizării. Lista 1 arată o versiune simplificată a ceea ce am făcut.

x = "salut"; // hello1

Acum permiteți optimizarea și comportamentul se va schimba. Din moment ce șirul din hello1 și hello2 este identic, compilatorul stochează o copie a "hello", astfel încât atât hello1 cât și hello2 se vor referi la această poziție. În acest caz, executarea liniilor x = "hello" și y = "hello" are ca rezultat rezultatul comparării lui x și y fiind TRUE.

Linia de jos este că dacă (x == y) nu a fost tipul corect de comparație. Trebuie folosită întotdeauna funcția strcmp () sau echivalentul acesteia.

În filmul „Jurassic Park“, există o scenă în care eroul Jeff Goldblum descoperă că metoda lor de a verifica dacă toate dinozaurii sunt prezente, contorizează numărul total de animale, și odată ce ajunge la un anumit punct, contul este închis. Că numărul de dinozauri a crescut, nu a fost observat pentru că personajele filmului, ajungând la numărul estimat de dinozauri, nu au continuat niciodată să înscrie. Animalele inteligente au dat seama cum să se înmulțească, în ciuda faptului că, probabil, toți dinozaurii clonați erau femei.

Goldblum erou sugerează că computerul a fost în căutarea unui număr mai mare de dinozauri, precum și numărul de animale care este mai mare decât suma inițială, grupul își dă seama că acestea au o animale preistorice mult mai mare decât se aștepta. Eu numesc această eroare "eroarea Parcului Jurasic". Aceasta este o eroare care stabilește limita superioară a oricărei valori, o credință falsă că un număr mai mare nu corespunde sau nu va contează atunci când apare un eveniment. Aceasta este o metodă rațională, care deseori simplifică programarea, dar din cauza stărilor neașteptate care sunt imperceptibile pentru sistem pot apărea.

Poate apare o astfel de eroare în software-ul dvs.? Dacă stocați un număr în variabila de 8-biți, trebuie să se oprească în detrimentul 255. Această valoare poate fi considerată ca un fel de stare de eroare sau ca o aproximare a valorii maxime posibile a variabilei în sistem. Care dintre aceste opțiuni este mai bună depinde de faptul dacă contorul ajunge la 255 într-o stare eronată sau într-o stare normală.

Când folosim numerele de partiție aritmetice pe întreg și părți fracționare, poate fi util pentru a limita valoarea acestor părți, astfel încât calculele folosind numere foarte mari nu duce la o revărsare de variabile.







Ca o ilustrare a "erorii Parcului Jurasic", voi da un exemplu din practica mea. Am avut un sistem care măsura fluxul de gaze. În mod obișnuit, sistemul controlat curge până la 15 l / min. Limita superioară a debitului măsurat a fost stabilită la 25 l / min. Credem că, chiar dacă fluxurile de gaze depășesc 25 l / min, le putem considera egale cu această valoare.

În unele cazuri, debitul a depășit de fapt 25 l / min, dar am crezut că aceste cazuri pot fi ignorate, deoarece sistemul nu era în control. Un astfel de caz a fost un test în care fluxurile detectate de doi senzori identici au fost comparate. Cu condiția ca senzorii să funcționeze corect și să furnizeze citiri exacte, fluxurile din fiecare senzor ar fi trebuit să se încadreze în toleranța dintre ele. Când presiunea externă în sistemul de alimentare cu gaz a fost foarte mare, testarea ar putea avea loc și cu bara de peste 25 l / min. Presupunând că calibrarea unui senzor a fost influențată, debitul măsurat de cei doi senzori a fost, de exemplu, de 26 l / min și de 29 l / min. Ambele valori au fost apoi rotunjite la 25 l / min din motivele descrise mai sus. Când a venit timpul să comparăm ambele valori, acestea erau egale cu 25 l / min și sunt egale una cu cealaltă. După ce am descoperit această situație, am interzis utilizarea testului comparativ pentru fluxuri peste 25 l / min.

Chiar dacă nu restricționați citirea citirilor din software, restricțiile asupra proiectului dvs. pot fi impuse de hardware. De exemplu, tensiunea de ieșire a senzorului va avea o limită superioară care limitează debitul. Vă recomandăm să utilizați întotdeauna senzori cu o gamă mai largă decât intervalul așteptat al sistemului dvs. Cu toate acestea, rețineți că va trebui să schimbați o gamă largă de senzori pentru rezoluția dispozitivului. Un senzor cu o gamă mai mică și o rezoluție mai mare poate fi mai precis, dar vă puteți afla într-un centru mort unde nu puteți vedea ce se întâmplă.

Văd periodic "eroarea Park Jurassic" în jurnalele de evenimente. Luați în considerare un dispozitiv care înregistrează evenimente excepționale din jurnal. Există un spațiu limitat pentru stocarea evenimentului, de exemplu, este creat un jurnal cu 30 de intrări. Fiecare intrare este o structură care conține detalii cum ar fi evenimentele, ora și, eventual, setările curente ale dispozitivului. Jurnalul complet conține 30 de evenimente. Cu toate acestea, dacă există 50 de evenimente, acestea vor fi în jur de 30 în jurnal, astfel încât numărul adevărat de evenimente este ascuns. În acest caz, problema poate fi atenuată prin utilizarea unei linii finale care conține numărul de evenimente neangajate. Deși această metodă nu vă ajută să cunoașteți detaliile evenimentelor, cel puțin veți ști că ceva lipsește. În timpul utilizării dispozitivului, acest contor vă va spune dacă valoarea a fost imbricată într-un volum mai mare de spațiu de memorie jurnal.

Există multe alte soiuri de "eroare de la Jurassic Park". După ce am suferit de multe ori din cauza acestei erori, sunt mai puțin dispusă să limitez maxim. Prefer să pun o limită în care să pot spune că sistemul va eșua când limita va fi depășită.

Un coleg a lucrat la o sumă de control care a fost utilizată pentru a confirma că copiile actualizate ale software-ului nostru sunt încărcate fără deteriorări. Ca una dintre etapele de testare, el a notat valorile sumelor de control pentru fiecare program executabil. Într-o zi, el a venit la mine și mi-a spus că a înțeles - despre care se gândea era probabil o eroare de compilator. Deoarece au existat multe greșeli în acest compilator, nu ne-a surprins cu adevărat.

Am salvat numărul versiunii în cod. În unele dintre proiectele noastre, acest număr a fost actualizat automat cu fiecare ansamblu și, prin urmare, cele două compilații nu ar fi identice. În acest proiect, numărul a fost modificat numai când programatorul a editat manual fișierul. În acest caz, nu a fost schimbat și nu ar putea fi motivul pentru schimbarea sumelor de control.

Am folosit macroul assert () foarte mult. Această macrocomandă utilizează macroul __LINE __ încorporat în compilator, care este egal cu linia curentă a fișierului compilat. Dacă am modificat numerele de linie, valoarea __ LINE __. utilizate de fiecare assert () ar fi diferite, iar aceste valori au fost stocate în programul sursă.

Niall Murphy "Cum să evitați bug-urile comune de firmware"

dintr-un anumit moment, buclele sunt construite astfel încât să excludă posibilitatea unei ieșiri a unei variabile într-un interval posibil.
și anume de exemplu, un ciclu în care variabila A variază de la 0 la 10 și comparăm condiția A = 10. în cazul în care dintr-o dată, indiferent de motiv, variabila A va merge dincolo de 10 pe care le efectua această operație, în timp ce numărul de neînțeles de ori revarsarile variabile și numărul pornește din nou de la zero. Dacă am verificat condiția A => 10? atunci cu o astfel de eșec ciclul ar fi mai scurt și eșecul nu este atât de critic, dar din nou depinde de condițiile specifice.

Ultima situație este într-adevăr un caz interesant și instructiv. Toate restul sunt triviale și sunt cunoscute chiar și elevilor.







Trimiteți-le prietenilor: