Fejl pr. enhed

En fejl pr. enhed eller en fejl i en uregistreret enhed ( engelsk  off-by-one error ) er en logisk fejl i algoritmen (eller i matematiske beregninger), herunder især en diskret version af overtrædelse af grænsebetingelser.

Der opstår ofte en fejl i programmeringen, når antallet af iterationer af en trin-for-trin- løkke er én mindre eller flere end nødvendigt. For eksempel, når en programmør sammenligner, angiver en programmør "mindre end eller lig" i stedet for "mindre end", eller laver en fejl og tæller begyndelsen af ​​sekvensen ikke fra nul, men fra en ( array- indeksering i mange programmeringssprog starter fra nul).

Iteration over elementerne i et array

Overvej et array af elementer, hvor elementer fra m -te til n -te inklusive behandles. Hvor mange medlemmer af arrayet vil blive behandlet? nm 's svar er en en-til-en fejl og et eksempel på en "hegn-stolpe" fejl. Det rigtige svar er n-m+1 .

For at reducere fejl på grund af uregistrerede enheder, er indekseringsintervallet ofte repræsenteret som halvåbne intervaller. Så området fra m til n (inklusive) er repræsenteret af området fra m (inklusive) til n+1 (ikke inklusive den sidste værdi). For eksempel kan en løkke , der går gennem fem værdier, skrives ved hjælp af et halvåbent interval fra 0 til 5 ( C-sprog ):

for ( i = 0 ; i < 5 ; ++ i ) { /* loop body */ }

Sløjfelegemet udføres startende fra i lig med 0; i bliver så til 1, 2, 3, og til sidst bliver i næste trin til 4. Når i bliver 5, er i<5 ikke opfyldt, og løkken slutter. Men hvis sammenligningsbetingelsen er <= (mindre end eller lig med), vil løkken køre seks gange: i vil påtage sig værdierne 0, 1, 2, 3, 4 og 5. På samme måde, hvis i er initialiseret til 1 i stedet for 0, vil der kun være 4 iterationer i løkken: jeg tager værdierne 1, 2, 3 og 4. Begge disse alternativer fører til en fejl på én.

En lignende fejl kan opstå, hvis en do-while loop bruges i stedet for en while loop (eller omvendt). Do-while-løkken garanterer mindst én iteration, fordi betingelsen kontrolleres, efter at loopens krop er udført.

Array-relaterede fejl kan også være resultatet af forskelle i programmeringssprog. At tælle fra nul er traditionelt, men nogle sprog tæller fra 1. Pascal og Fortran kan definere indeks [1] . Dette giver dig mulighed for at tilpasse array-modellen til emneområdet.

Hegnsstolpe fejl

Hegnspælsfejlen (nogle gange kaldet telegrafpæl eller lygtepælsfejl) er et særligt tilfælde af fejl pr. enhed. Følgende opgave illustrerer denne fejl:

Man sætter et lige hegn 30 meter langt og sætter stolper op for hver 3. meter. Hvor mange stænger har du brug for?

Det "åbenlyse" svar ved første øjekast, 10, er forkert.
Hegnet har 30 : 3 = 10 sektioner. Men der kræves 11 søjler, en mere.

Den omvendte fejl opstår, når antallet af kolonner er kendt, og antallet af sektioner antages at være lig med antallet af kolonner. I virkeligheden er antallet af sektioner en mindre end antallet af kolonner.

Mere generelt kan problemet formuleres som følger: hvis der er n telegrafpæle, hvor mange mellemrum er der så mellem dem?

Det rigtige svar kan være n-1, hvis linjen af ​​pæle er åben i begge ender; n hvis søjlerne danner en cirkel; n + 1 - hvis de frie mellemrum i begge ender betragtes som huller. Den nøjagtige definition af problemet skal undersøges nøje, da en løsning, der er korrekt i én situation, kan give et fejlagtigt resultat i en anden. Hegnspælsfejlen opstår ved at tælle stolper i stedet for mellemrum mellem dem, eller omvendt, og ved at negligere spørgsmålet om, hvorvidt den ene eller begge ender af en række skal tages i betragtning.

Hegnspælsfejlen kan også vise sig ved optælling af andre elementer end længder. Et eksempel er tidens pyramide , som skal bestå af 120 blokke, som hver placeres på sin plads med et interval på 10 år. Det tager 1190 år at bygge fra starten af ​​den første blok til den sidste blok, ikke 1200. ikke med en undtagelse. På grund af dette gentages skudåret i beregningen efter 3 år og ikke efter 4.

Hegnspælsfejlen kan i sjældne tilfælde være forårsaget af en uventet rækkefølge af inputdata, som for eksempel fuldstændig kan ophæve effektiviteten ved at bruge et binært træ eller udføre en hashfunktion . Denne fejl har at gøre med forskellen mellem algoritmens forventede og værste tilfælde adfærd.

For store tal er fejlen pr. enhed ofte ikke så vigtig i et bestemt tilfælde. Med små tal, og i nogle specifikke tilfælde, hvor præcision er altafgørende, kan forekomsten af ​​en en-til-en fejl være katastrofal. Nogle gange kan en fejl gentages, og derfor forstærkes, ved at personen laver den forkerte beregning, hvis den næste person laver den fejl igen (selvfølgelig kan denne fejl også laves omvendt).

Som et eksempel på en sådan fejl kan vi tage linspace()-funktionen [2] fra Matlab -beregningssproget , hvis parametre er: den mindste værdi, den største værdi og antallet af værdier, og ikke: den mindste værdi, den største værdi og antallet af trin. En programmør, der misforstår, hvad den tredje parameter er, vil antage, at linspace(0,10,5) vil generere sekvensen [0,2,4,6,8,10], men i stedet få [0, 2,5, 5, 7,5, 10 ].

Sikkerhedsproblemer

En almindelig en-til-en-fejl, der fører til et sikkerhedsproblem, er den forkerte brug af strncat()- funktionen fra C - standardbiblioteket . En almindelig misforståelse forbundet med strncat() er, at en null-byte [3] ikke kan skrives længere end strengens længde. Funktionen skriver faktisk en null-byte ud over den angivne strenglængde, hvis den tredje parameter er lig med eller større end denne længde. Følgende kode indeholder netop en sådan fejl:

void foo ( const char * s ) { charbuf [ 15 ] ; buf [ 0 ] = '\0' ; strncat ( buf , s , sizeof ( buf )); // FEJL - sidste parameter skal være lig med sizeof(buf)-1 }

En fejl er almindelig ved brug af C-standardbiblioteket, fordi det ikke har en ensartet tilgang til, om 1 skal trækkes fra eller ej: funktioner som fgets() og strncpy() vil aldrig overskride deres specificerede længde (fgets() trækker selv 1 fra og udtrækker (længde-1) bytes), mens andre funktioner som strncat() skriver forbi længden angivet for strengen. Af denne grund skal programmøren huske, hvilke funktioner der kræver at trække 1 fra.

På nogle systemer (især dem med endian endian-arkitektur) kan dette resultere i, at betydelige bytes bliver overskrevet på processtakken, hvilket kan skabe en tilstand, hvor en angriber får data, der tillader ham at kalde en procesprocedure [4] .

En tilgang, der kan bruges til at løse sådanne problemer, er at bruge en modifikation af disse funktioner, der tæller antallet af skrevne bytes under hensyntagen til længden af ​​bufferen, i stedet for at skrive eller læse det maksimale antal bytes. Eksempler er funktionerne strlcat() og strlcpy() , som ofte betragtes som "sikre", fordi de forhindrer utilsigtede skrivninger ud over slutningen af ​​bufferen (i koden ovenfor eliminerer kald af strlcat(buf, s, sizeof(buf)) en sikkerhedsfejl).

Se også

Noter

  1. Traditionelt er det i Pascal-sproget sædvanligt at begynde at tælle fra én.
  2. en vektor med jævnt fordelte elementer . Dato for adgang: 4. februar 2015. Arkiveret fra originalen 4. februar 2015.
  3. Et tegn, hvis en-byte kode er nul. C-biblioteket opretholder en regel om, at en sådan byte markerer slutningen af ​​en streng
  4. At skrive data over en buffergrænse kaldes en bufferoverløbsfejl .

Links