Egy-egy hiba- Off-by-one error
Egy off-by-egy hiba vagy off-by-egy hiba (ismert rövidítések OBOA , OBO , OB1 és OBOB ) egy logikai hiba járó diszkrét egyenértékű egy határfeltétel . Gyakran előfordul a számítógépes programozásban, amikor egy iteratív ciklus egyszer túl sok vagy túl kevés iterációt végez . Ez a probléma akkor merülhet fel, ha egy programozó hibákat követ el, például azt, hogy a "kisebb vagy egyenlő, mint" ahol "kisebb, mint" kellett volna használni az összehasonlításban, vagy nem veszi figyelembe, hogy egy sorozat nulláról indul, nem pedig egyről ( mint sok nyelven a tömbindexeknél). Ez történhet matematikai összefüggésben is.
Looping tömbök felett
Tekintsünk egy sor elemet, és az m és n közötti elemeket (beleértve) fel kell dolgozni. Hány elem van? Az intuitív válasz lehet n - m , de ezt ki kell kapcsolni, és kerítésoszlop hibát jelez ; a helyes válasz ( n - m ) + 1.
Emiatt a számítástechnika tartományait gyakran félig nyitott intervallumok képviselik ; a m -től n -ig terjedő tartományt (beleértve) az m (beleértve) és n + 1 (kizárólagos) tartomány jelenti, hogy elkerüljük a kerítésoszlop hibáit. Például egy ötször (0-tól 4-ig) ismétlődő ciklus félig nyitott intervallumként írható 0-tól 5-ig:
for (index = 0; index < 5; index++)
{
/* Body of the loop */
}
A hurok törzsét először 0 -val egyenlő indexszel hajtjuk végre ; Az index ezután 1, 2, 3 és végül 4 lesz az egymást követő iterációk során. Ekkor az index 5 lesz, tehát az <5 index hamis, és a ciklus véget ér. Ha azonban az összehasonlítás < or = (kisebb vagy egyenlő) lenne, a ciklust hatszor hajtanák végre: az index a 0, 1, 2, 3, 4 és 5 értékeket veszi fel. Hasonlóképpen, ha az indexet inkább 1 -re inicializálják mint 0, csak négy iteráció lenne: az index az 1, 2, 3 és 4 értékeket veszi fel. Mindkét alternatíva egyedi hibákat okozhat.
Egy másik ilyen hiba akkor fordulhat elő, ha a do-while ciklus helyett használjuk a while (vagy fordítva). A do-while ciklus garantáltan legalább egyszer lefut.
A tömbhöz kapcsolódó zavart a programozási nyelvek különbségei is okozhatják. A 0-tól való számozás a leggyakoribb, de egyes nyelvek 1-el kezdik a tömbszámozást. A Pascal tartalmaz tömböket a felhasználó által meghatározott indexekkel. Ez lehetővé teszi a tömbindexek modellezését a problémás tartomány után.
Kerítésoszlop hiba
A kerítésoszlop hiba (amelyet időnként távíróoszlopnak, lámpaoszlopnak vagy kerítéshibának neveznek ) egy-egy hibatípus. Ennek a hibának a korai leírása megjelenik Vitruvius műveiben . A következő probléma szemlélteti a hibát:
Ha 30 láb hosszú, egyenes kerítést épít, és 3 láb távolságra lévő oszlopokkal, hány oszlopra van szüksége?
10 hozzászólás közös válasza rossz. Ez a válasz abból származik, hogy a kerítés hosszát elosztjuk az egyes oszlopok közötti távolságokkal, és a hányadost tévesen az oszlopok számának minősítik. Valójában a kerítés 10 szakaszból és 11 oszlopból áll.
Ebben a forgatókönyvben egy n szakaszú kerítésnek n + 1 oszlopa lesz. Ezzel szemben, ha a kerítés n oszlopot tartalmaz , akkor n - 1 szakaszt tartalmaz. Ezt az összefüggést fontos figyelembe venni, amikor a fordított hibát kezeljük. A fordított hiba akkor fordul elő, ha a bejegyzések száma ismert, és a szakaszok számát azonosnak feltételezzük. A kerítés kialakításától függően ez a feltételezés lehet helyes vagy helytelen.
A következő probléma a fordított hibát mutatja:
Ha n bejegyzésed van, hány rész van közöttük?
A kerítés kialakításának értelmezése megváltoztatja a választ erre a problémára. A kerítés megfelelő szakaszszáma n- 1, ha a kerítés szabadon álló vonalszakasz, amelyet mindkét végén egy oszlop határol (pl. Kerítés két átjáró közötti rés között), n, ha a kerítés egy teljességet alkot, szabadon álló hurok (pl. lezárással hozzáférhető ház, például bokszgyűrű), vagy n + 1, ha oszlopok nem fordulnak elő egy vonalszakaszhoz hasonló kerítés végén (pl. kerítés és falhoz rögzítve) két épület). A probléma pontos meghatározását alaposan meg kell fontolni, mivel az egyik helyzet beállítása rossz választ adhat más helyzetekre. A kerítésoszlop hibái a dolgok számolásából, nem pedig a köztük lévő szóközökből származnak, vagy fordítva, vagy ha figyelmen kívül hagyják, hogy számolni kell -e a sor egyik vagy mindkét végét.
A kerítésoszlop hibái a hosszúságtól eltérő egységekben is előfordulhatnak. Például az időpiramis , amely 120 blokkból áll, 10 éves időközönként a blokkok között, a tervek szerint 1190 évet vesz igénybe (nem 1200) az első blokk telepítésétől az utolsó blokkig. Az egyik legkorábbi kerítéshiba az időhöz kapcsolódott, ahol a Julián -naptár eredetileg helytelenül számította ki a szökőévet , nem csak kizárólagosan, hanem csak háromévente, szökőévet produkálva.
A „kerítésoszlop hibája” ritka esetekben utalhat a bemeneti értékek váratlan szabályszerűségei által előidézett hibára, amely (például) teljesen meghiúsíthatja az elméletileg hatékony bináris fa vagy hash függvény megvalósítását. Ez a hiba magában foglalja az algoritmus várható és legrosszabb viselkedése közötti különbséget .
Nagyobb számban gyakran nem jelent komoly problémát. Kisebb számokban, de bizonyos esetekben, amikor a pontosság a legfontosabb, egy-egy hiba elkövetése katasztrofális lehet. Néha egy ilyen probléma megismétlődik, és emiatt súlyosbodik, ha valaki helytelen számítást ad át, ha a következő személy ismét elköveti ugyanazt a hibát (természetesen a hiba is megfordulhat).
Erre példa a hiba akkor fordulhat elő a számítógépes nyelv MATLAB a linspace() lineáris interpoláció funkció, melynek paraméterei , és nem . Az a programozó, aki félreérti a harmadik paramétert a lépések számának, remélheti, hogy eléri a sorozatot, de megkapja .
(lower value, upper value, number of values)(lower value, upper value, number of increments)linspace(0,10,5)[0, 2, 4, 6, 8, 10][0, 2.5, 5, 7.5, 10]
Biztonsági vonatkozások
A C-szabványos könyvtári strncat rutin helytelen használata okozza a gyakori hibát, amely biztonsággal kapcsolatos hibát eredményez . Általános tévhit, strncathogy a garantált null felmondás nem ír a maximális hosszon túl. A valóságban egy befejező null karaktert ír egy bájttal a megadott maximális hosszon túl. A következő kód tartalmaz egy ilyen hibát:
void foo (char *s)
{
char buf[15];
memset(buf, 0, sizeof(buf));
strncat(buf, s, sizeof(buf)); // Final parameter should be: sizeof(buf)-1
}
Az egyedi hibák gyakoriak a C könyvtár használatakor, mivel nem egységesek abban, hogy ki kell-e vonni 1 bájtot-olyan függvények, mint fgets()és strncpysoha nem fognak az általuk megadott hosszúság felett írni ( fgets()kivonja magát 1, és csak lekéri (hossz - 1) bájt), míg mások, mint például, strncataz általuk megadott hosszon túl írnak. Tehát a programozónak emlékeznie kell arra, hogy mely funkciókhoz kell kivonni az 1 -et.
Egyes rendszerek ( little endian architektúrák különösen), ez azt eredményezheti, hogy a felülírás a legkevésbé fontos bájt a keret mutatót . Ez kihasználható állapotot okozhat, amikor a támadó eltérítheti a hívó rutin helyi változóit.
Az egyik megközelítés, amely gyakran segít elkerülni az ilyen problémákat, az, hogy ezeknek a függvényeknek a változatait használja, amelyek a puffer teljes hossza alapján számítják ki, hogy mennyit kell írni, és nem az írható karakterek maximális számát. Ilyen funkció például strlcatés strlcpyvannak, és gyakran tekintik a „biztonságosabb”, mert könnyebb, nehogy véletlenül írásban elmúlt vége a puffer. (A fenti kódpéldában a hívás strlcat(buf, s, sizeof(buf))helyett eltávolítaná a hibát.)
Lásd még
További irodalom
- Matt Parker (2021). Humble Pi: Amikor a matematika téved a való világban . Riverhead könyvek. ISBN 978-0593084694.
Jegyzetek és hivatkozások
Megjegyzések
Hivatkozások
- Egy korábbi változata ezt a cikket alapul túlcsordulásokat hiba a proxi , használt engedéllyel .
- Dijkstra, Edsger Wybe (2008. május 2.). "Miért kell a számozást nulláról kezdeni (EWD 831)" . EW Dijkstra Archívum . Texas Egyetem Austinban . Letöltve: 2011-03-16 .
- A közös gyengeség-felsorolási rendszerben ez a probléma CWE-193 néven szerepel: Egyszeri hiba