Alweer geen Excel

Errors en IOResult

Arnout van Kempen schrijft in deze rubriek over pret maken met computers. Hij gaat aan de slag met Pascal.

Als een bestand benaderd wordt dat niet bestaat, dan krijg je een runtime-error en je programma stopt. In essentie is dat in DOS niet anders dan in Linux en in Pascal niet anders dan in C. Modernere talen als Rust dwingen de programmeur error handling in te richten, of dat heel bewust achterwege te laten. Turbo Pascal werkt meestal omgekeerd. Het kan wel, maar standaard werkt het zo:

  1. Fouten rond bestandstoegang worden gesignaleerd en afgehandeld met een foutmelding en een exit.
  2. Fouten in indexen en stack overflows worden simpelweg genegeerd en de meest basale memory safety is er dus niet. Net als in C.

Je kan echter kiezen dat wat beter te doen. Bestandstoegang kan je afvangen door géén automatische check te doen, terwijl je geheugenfouten juist kan afvangen door wel een automatische check te doen.
Bij bestandstoegang krijg je, als je de automatische check uit zet, een foutcode die je zélf moet opvragen, maar je programma exit niet. Die foutcode heet IOResult.

Je maakt die keuze met een compiler directive: {$I+} of {$I-}

Standaard staat Turbo Pascal op {$I+} (I/O checking on). Bij een I/O-fout krijg je onmiddellijk een runtime-error en het programma stopt met een foutmelding. Zet je bewust {$I-} (I/O checking off), dan stopt het programma niet. De mislukte I/O-aanroep zet IOResult (0 = oké, ≠0 = fout). Jij moet dan zélf lezen wat er misging en daarop reageren.

Mits je fouten afvangt, levert dat dus een eleganter resultaat op.

{$I-}              { automatische I/O-check uit }
Assign(F, 'BESTAATNIET.TXT');
Reset(F);
if IOResult <> 0 then
  Writeln('Fout: bestand niet gevonden');
{$I+}               { optioneel: weer veilig aan }

Je krijgt de foutcode één keer; bij het lezen wordt deze direct teruggezet naar 0.

Wat gebeurt er als je niet checkt? Het programma loopt door, maar de I/O-operatie is niet gelukt. Data is niet gelezen of niet geschreven; de foutcode blijft klaarstaan in IOResult, totdat het programma deze uitleest. Doe je dat niet, dan merk je de mislukking pas later als je data mist of corrupte bestanden krijgt.

Ter vergelijking een moderne taal als Rust:

Rust werkt zonder klassieke exceptions. In plaats daarvan dwingt Rust je fouten expliciet af te handelen met Result<T, E> (of via ?). Conceptueel is dat wat je in Turbo Pascal met {$I-} + IOResult met de hand doet.

use std::fs::File;
use std::io::{self, Read};

fn read_file(path: &str) -> io::Result<String> {
    let mut f = File::open(path)?;    // ? = geef fout door (propagate)
    let mut s = String::new();
    f.read_to_string(&mut s)?;        // opnieuw: explicit handling
    Ok(s)
}

fn main() {
    match read_file("DATA.TXT") {
        Ok(text) => println!("Inhoud:\n{}", text),
        Err(e)   => eprintln!("Fout: {}", e),
    }
}

Rusts ? is grofweg: doe IOResult en geef bij fout netjes door”. Waar Turbo Pascal standaard crasht ({$I+}), dwingt Rust je tot structurele foutafhandeling.

Welke fouten moet je zoal afvangen in Pascal?

Veelvoorkomende I/O-fouten
Code
Geen fout
0
File not found
2
Path not found
3
Too many open files / Disk full
4
Access denied
5
Invalid handle
6

Niet alle fouten zijn I/O. Enkele typische runtime-errors (afhankelijk van compiler-switches): 

Veelvoorkomende runtime errors
Code
Division by zero
200
Range check error (mits {$R+})
201
Stack overflow
202
Heap overflow
203
Invalid pointer operation
204
Floating-point overflow
205

Met{$R+} en {$S+} zorg je voor basale memory safety. Het programma controleert dan of je niet buiten vastgelegde ranges komt, of dat je stack niet te groot wordt. 

Bijvoorbeeld:

Var A: Array[1..10] of Integer;
A[11] := 42;

Met {$R+}: runtime error 201 (range check error), maar standaard, met {$R-}, geen foutmelding. De waarde 42 wordt nu in onbeschermd geheugen geschreven.

{$S+} controleert of je stack niet overloopt.

Procedure Recurse;
Begin
  Recurse;   { oneindige recursie }
End;

Met {$S+}: runtime error 202 (stack overflow). Zonder: geheugenonveiligheid en onvoorspelbare crashes. 

Dat is de kern van foutafhandeling in Turbo Pascal: simpel, geen standaard veiligheid en dus discipline van de programmeur. Als je niet oplet, word je er snel laks van (zeg ik uit ervaring).

Arnout van Kempen is naast computernerd ook directeur compliance & risk bij aaff. Hij schrijft op persoonlijke titel.

Gerelateerd

reacties

Reageer op dit artikel

Spelregels debat

    Aanmelden nieuwsbrief

    Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

    Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.