Ok, denne er litt nerdete. Hvis du ikke er nerdete så får du lese noe annet - eller skjerpe deg.
En gang på starten av 80-tallet studerte jeg på Blindern og hadde bijobb som lukevakt.
"Luka" var en .. luke .. i kjelleren i matematikkbygningen (Niels Henrik Abels hus) på Blindern der deltidsansatte informatikkstudenter svarte på spørsmål rundt bruk og programmering av universitetets DEC-10-anlegg. Det var ofte stille, spørsmålene var som regel trivielle, og vi hadde god tid til å jobbe med våre egne studier innimellom besøkene vi fikk.
De mest utfordrende oppgavene våre pleide å være folk som kom innom med et program og mente å ha funnet en "feil i systemet" - dvs. at programmet deres gikk feil ikke på grunn av noe de selv hadde gjort men en feil i selve maskinen. Disse oppgavene var ikke utfordrende fordi vi måtte finne frem til feil i DEC-10. Neida, de var utfordrende fordi skylden alltid lå hos personen som kom på besøk, og det var vår jobb å (a) finne feilen og (b) hjelpe vedkommende, begge deler uten at han eller hun ble dødelig såret eller fornærmet over å ikke bli trodd.
Men den gangen jeg skal fortelle om nå var annerledes, selv om jeg selvsagt ikke visste det til å begynne med.
En nydelig høstdag satt jeg der på min plass i Luka i underetasjen i mattebygget, og fikk besøk av en statistiker som var skikkelig frustrert. Han fortalte at han hadde rekompilert et av programmene sine med den nye FORTRAN-77-kompilatoren, og nå påsto programmet av 2 var 7.
Jeg sukket litt innvendig, forberedte meg mentalt på en halvtime med kombinert debugging og diplomati, og ba om å få se hvor problemet oppsto. Statistikeren dro opp av veska si to papirbunker, den ene en utskrift av programmet, den andre en utskrift av dataene programmet genererte.
Vi tittet på de to papirbunkene, sammenlignet operasjoner og resultat. Jeg sa "det kan da ikke stemme". Han sa "akkurat". Jeg klødde meg i hodet. Han hadde allerede bare flekker.
Det var et stort, stygt og fælt program, sånn som FORTRAN-programmer skrevet av ikkeprogrammerere pleier å være. (FORTRAN-programmer skrevet av programmerere er gjerne litt bedre). Det var massevis av obskur logikk der. Det hyppigst brukte uttrykket var GOTO. Det var på ingen måte klart for en ikke-statistiker hva programmet egentlig gjorde.
Men en ting var helt klart: her var det noe hakke steike gæli - og det var ikke lett å se hvordan det skulle kunne være statistikerens skyld.
Et sted langt langt nede i programmet skrev det ut en del kontrolldata som skulle brukes av et annet program, og en av linjene i programmet så sånn ut:
WRITE (7,1102) 2
På FORTRANsk betyr dette "skriv ut tallverdien 2 til filen åpnet på kanal 7 med hjelp av formatteringsanvisningen du finner på linje 1102".
Så tittet vi bort på papirbunken som viste hva programmet hadde skrevet ut på dette punktet. Og joda, der sto det "7". Jeg klødde meg litt mer i hodet.
Det ble fort klart at dette ikke var noe jeg kunne finne ut av i en fei, så jeg fikk en elektronisk kopi av programmet sånn at jeg kunne kjøre det selv, sammen med en oppskrift på hvordan det skulle brukes.
Om ettermiddagen stengte Luka, men jeg ble sittende utover kvelden, for dette var noe jeg bare måtte finne ut av. Jeg kompilerte programmet, linket det, lastet inn DEC-10-debuggeren DDT og satte i gang.
Og etter noen timer kvalitetstid foran VT100-terminalen kunne jeg konstatere at statistikeren hadde rett: Han hadde kommet over en feil i systemet - eller rettere sagt i den nye FORTRAN-77-kompilatoren.
Og her er hva som foregikk - i all sin grusomhet om enn noe forenklet (av både pedagogiske og hukommelsesmessige årsaker..):
- Kompilatoren var smart nok til å optimalisere bruk av konstanter. Det vil si at dersom tallverdien 2 var i bruk flere steder i programmet så la den tallverdien 2 på ett sted i hukommelsen, og refererte til denne konstantverdien fra alle stederi programmet som trengte en 2.
- Ett sted i programmet fantes det en subrutine som var definert noe ala SUBROUTINE FOO(BAR). Når man kaller subrutiner i FORTRAN så overføres parameterne "by reference" - konsekvensen av dette er at en subrutine kan endre parameterverdier med å endre dem lokalt. Subrutinen FOO i programmet gjorde dette, den endret BAR til å være BAR+5.
- Et annet sted i programmet fantes subrutinekallet FOO(2).
- Etter at punkt 3 var utført var minneverdien som egentlig skulle vært en konstant 2 blitt endret til 7.
- Noe senere kom programmet til WRITE-uttrykket som skulle skrive ut 2. Dette skrev ut det som lå i minnet der kompilatoren hadde plassert "2", men der lå det nå 7.
- Ikke syt, jeg sa at dette var nerdete.
Kompilatorfeil! Hvem skulle trodd det.
I statistikerens program var det enkelt å komme opp med en workaround: I stedet for å kalle FOO(2) lagde vi en variabel X, satte X til å være 2, og kalte FOO(X). Da ble X endret men det gjorde ikke noe siden den ikke ble brukt til noe annet.
Den egentlige feilen - i kompilatoren - ble løst noen måneder senere med en oppdatering fra Digital. Jeg husker ikke helt hva rettelsen besto av, men på andre maskintyper er det vanlige å skrivebeskytte de delene av hukommelsen hvor man legger konstanter (og programkode). På Unix ville statistikeren f.eks. fått en (for ham) helt uforståelig "segmentation fault" (SIGSEGV) når han prøvde å kjøre programmet sitt.
Det er etterhvert blitt ganske mange år siden sist jeg så innsiden av et FORTRAN-program, og det er jeg stort sett bare glad for.
Leave a comment