IN 147 Program og maskinvare. Vanlige feil ved bruk av pekere Feilsøking Debuggere

Like dokumenter
IN 147 Program og maskinvare

Pekere og vektorer. Dagens tema. I C gjelder en litt uventet konvensjon:

Dagens tema. Det siste om C Pekere og vektorer. Pekere til pekere. Vanlige pekerfeil. struct-er og typedef. Lister. Feilsøking

Dagens tema INF1070. Info om C. Cs preprosessor. Feilsøking. Dag Langmyhr,Ifi,UiO: Forelesning 31. januar 2005 Ark 1 av 29

Informasjon om C. Dagens tema INF1070 INF1070 INF1070 INF1070. Den viktigste kilden til informasjon om C (utenom en god. C-funksjonene.

IN 147 Program og maskinvare

Dagens tema. Nyttige programmer Programmet make. Hvis én fil endres, hvilke filer må da kompileres på nytt?

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Dagens tema. Nyttige programmer Programmet make. Flyt-tall Representasjon av flyt-tall. Standarden IEEE 754. Systemkall i Unix

Programmeringsspråket C Del 3

Dagens program. Operativsystemer Prosesser og systemkall i UNIX Hente prosessens nummer Starte prosesser Vente på prosesser Utføre programmer

Debuggere En «debugger» er et meget nyttig feilsøkingsverktøy. Det kan analysere en program dump, Dagens tema INF1070 INF1070 INF1070 INF1070

Dagens tema INF1070. Signaturer. Typekonvertering. Pekere og vektorer. struct-er. Definisjon av nye typenavn. Lister

Dagens tema: Enda mer MIPS maskinkode

IN 147 Program og maskinvare

Dagens tema. Adresser som parametre Dynamisk allokering Signaturer Definisjon av nye typenavn Typekonvertering Pekere og vektorer

Signaturer. Dagens tema. En vanlig feil int-funksjon. Dette kan noen ganger gi rare feilmeldinger: INF1070 INF1070 INF1070 INF1070

Dagens tema INF1070. Vektorer (array er) Tekster (string er) Adresser og pekere. Dynamisk allokering

Oversikt over IN147(A):

Programmeringsspråket C

Del 4 Noen spesielle C-elementer

Kapittel 1 En oversikt over C-språket

Del 1 En oversikt over C-programmering

Vektorer. Dagens tema. Deklarasjon. Bruk

Dagens tema C, adresser og pekere

Ark 3 av 26. printf("i adresse %08x ligger b med verdien %d.\n", &b, b); printf("i adresse %08x ligger a med verdien %d.

Debugging. Tore Berg Hansen, TISIP

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

IN 147 Program og maskinvare

IN 147 Program og maskinvare

Dagens tema. Representasjon av mantissen En desimalbrøk: 1 1, INF1070 INF1070 INF1070 INF1070

Nybegynnerkurs i C. Øyvind Grønnesby. 14. oktober Introduksjon Typer Operatorer Kontrollstrukturer Pekere Makroer Lenker

Dagens tema INF2270. Flyt-tall (B&O H-boken 2.4, 3.14) Hvordan lagres de? Hvordan regner man med dem? Bit-fikling (B&O H-boken 2.1.

Programmeringsspråket C Del 2

Tall. Binære regnestykker. Binære tall positive, negative heltall, flytende tall

Programmeringsspråket C Del 2

IN 147 Program og maskinvare

Programmeringsspråket C Del 2

Hvordan en prosessor arbeider, del 1

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

Reelle tall på datamaskin

Dagens tema. Representasjon av mantissen En desimalbrøk: 1 1, INF2270 INF2270 INF2270 INF2270

IN 147 Program og maskinvare

Dagens tema. Mer MIPS maskinkode. Maske-operasjoner Skift-operasjoner Lesing og skriving Pseudo-instruksjoner Mer om funksjonskall Registeroversikt

Dagens tema INF2270. Signaturer. Typekonvertering. Pekere og vektorer. struct er. Definisjon av nye typenavn. Lister. Info om C

Dagens tema INF1070. Vektorer (array-er) Tekster (string-er) Adresser og pekere. Dynamisk allokering

Dagens tema INF2270. Flyt tall (B&O H boken 2.2.3) Hvordan lagres de? Hvordan regner man med dem? Overflyt (B&O H boken )

Forelesning Datatyper Kap 5.2 Instruksjonsformat Kap 5.3 Flyttall App B

IN 147 Program og maskinvare. Dagens tema

Programmeringsspråket C

Tall. Posisjons-tallsystemer. Representasjon av heltall. Tall positive, negative heltall, flytende tall. Tekst ASCII, UNICODE XML, CSS

Programmeringsspråket C Del 2. Hans Petter Taugbøl Kragset

Programmeringsspråket C

Programmeringsspråket C Del 3. Hans Petter Taugbøl Kragset

Programmeringsspråket C Del 2. Michael Welzl

Rutiner [REB&DRO H 3.7]

En oppsummering (og litt som står igjen)

Litt om Javas håndtering av tall MAT-INF 1100 høsten 2004

MAT-INF 1100: Obligatorisk oppgave 1

2 Om statiske variable/konstanter og statiske metoder.

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

Den siste dagen. Pensumoversikt Hovedtanker i kurset Selvmodifiserende kode Overflyt Veien videre... Eksamen

Dagens tema. Dynamisk allokering Signaturer Definisjon av typer og nye typenavn Typekonvertering Pekere, vektorer og lister Dokumentasjon

MAT-INF 1100: Obligatorisk oppgave 1

Programmering i C++ Løsningsforslag Eksamen høsten 2005

Signaturer. Dagens tema

Pensum Hovedtanker Selvmodifiserende Overflyt Veien videre Eksamen. Oppsummering

Kjøresystemer. Hva er et kjøresystem? Den abstrakte maskinen SIMPLESEM (2.6) Klassifisering av språk: Parametre (2.7.7) Statiske språk (

TDT4105/TDT4110 Informasjonsteknologi grunnkurs:

Dagens tema INF2270. Cs preprosessor. Separat kompilering av C funksjoner. C og minnet. Dag Langmyhr,Ifi,UiO: Forelesning 5. februar 2007 Ark 1 av 15

Dagens tema. Funksjonskall. Flyt-tall. Rekursive kall Lokale variable. Hvordan lagres de? Hvordan regner man med dem?

TDT4105/TDT4110 Informasjonsteknologi grunnkurs:

TALL. Titallsystemet et posisjonssystem. Konvertering: Titallsystemet binære tall. Det binære tallsystemet. Alternativ 1.

EKSAMEN. Operativsystemer. 1. Læreboken "A Practical Guide to Red Hat Linux" av Mark Sobell 2. Maks. tre A-4 ark med selvskrevne notater.

INF1040 Digital representasjon TALL

IN 147 Program og maskinvare

Del 2 Tabeller, arrays, strenger

Del 3. Pekere RR 2016

Notater: INF2270 Assembler

Dagens tema. Oppsummering om assemblerspråk. Programmering i C. Bakgrunn. Et minimalt eksempel med forklaring. Datatyper i C.

Programmeringsspråket C Del 3. Michael Welzl

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

Oppbygningen av en datamaskin Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Eivind Gard Lund. 24. Mars 2009 Foilene bygger på 2009 utgaven av Andreas Svendsen

2 Om statiske variable/konstanter og statiske metoder.

Ark 1 av 18. programmeringsspråkenes. Velkommen til IN 211. verden. IN 211 Programmeringsspråk

Kort om meg. INF1000 Uke 2. Oversikt. Repetisjon - Introduksjon

INF225 høsten 2003 Prosjekt del 4: kodegenerering

Dagens tema: Datastrukturer

Dagens tema. Mer om C Enkle datatyper Sammensatte datatyper: Vektorer og matriser Tekster Mengder Strukturer Unioner Ringbuffere

Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

INF1000: noen avsluttende ord

TDT4110 IT Grunnkurs Høst 2015

Det viktigste i en moderne datamaskin er hovedkortet («motherboard»):

Transkript:

Dagens tema Vanlige feil ved bruk av pekere Feilsøking Debuggere lint Kompilatormeldinger Egne testutskrifter Flyt-tall (P&H: 4.8) Representasjon av flyt-tall Standarden IEEE 754 MIPS-operasjoner på flyt-tall Ark 1 av 36 Forelesning 7.3.2001

Vanlige pekerfeil Det er noen feil som går igjen: Glemme initiering av pekeren: long *p; printf("verdien er %ld.\n", *p); Glemme frigjøring av objekt: long *p; p = (long*)malloc(sizeof(long)); p = NULL; Det allokerte objektet vil nå være utilgjengelig, men vil fortsatt «flyte rundt» og oppta plass så lenge programmet kjører. Dette kalles en minnelekkasje. Forelesning 7.3.2001 Ark 2 av 36

La en global peker peke på lokal variabel: long *p; void f(void) { long x; } p = &x; f(); p peker nå på en variabel som ikke finnes mer. Stedet på stakken der x lå, kan være tatt i bruk av andre funksjoner. Peke på resirkulert objekt: long *p, *q; p = q = (long*)malloc(sizeof(long)); free(p); p = NULL; q peker nå på et objekt som er frigjort og som kanskje er tatt i bruk gjennom nye kall på malloc. Forelesning 7.3.2001 Ark 3 av 36

Feilsøking Hva gjør vi når alt bare går galt? #include <stdio.h> #include <stdlib.h> int *vec[10]; int main(void) { int i; for (i = 0; i<10; ++i) { vec[1] = (int*)malloc(sizeof(int)); *vec[i] = i; } } for (i = 9; i>=0; --i) { printf("vec[%d] peker på %d.\n", i, *vec[i]); } return 0; Forelesning 7.3.2001 Ark 4 av 36

Forsøk på å kjøre dette programmet gir bare Segmentation Fault Dette forteller om en ulovlig peker/adresse, men hvor? I hvilken programkodelinje skjedde feilen? Hva var situasjonen da? Nærmere bestemt vil vi gjerne vite Hva inneholder de ulike variablene? Hva er kallkjeden (dvs. hvilke funksjoner er kalt, og hvorfra)? Forelesning 7.3.2001 Ark 5 av 36

Debuggere En «debugger» er et meget nyttig feilsøkingsverktøy. Det kan analysere en program-dump, vise innholdet av variable, vise hvilke funksjoner som er kalt, kjøre programmet én og én linje, og kjøre til angitt stoppunkter. Debuggeren gdb er laget for å brukes sammen med både cc og gcc. Den har et vindusgrensesnitt som heter ddd. For å kunne bruke gdb/ddd må to ting gjøres: kompilere programmene med opsjonen -g angi at vi ønsker og har ubegrenset plass til programdumper: ulimit -c unlimited hvis vi bruker kommandotolkeren bash. Vi må også huske å fjerne programdumpfilene selv; de er store! Forelesning 7.3.2001 Ark 6 av 36

Programdumper Når et program terminerer på grunn av en feil («aborterer»), prøver det ofte å skrive innholdet av hele prosessen til en fil slik at det kan analyseres siden. 1. Programmet kompileres med debuggingsinformasjon: maskin navn> cc -g test-gdb.c -o test-gdb 2. Programmet kjøres: maskin navn> test-gdb Segmentation Fault (core dumped) maskin navn> ls -l core -rw------- 1 kritisk kritisk 95408 Mar 5 15:20 core Dette kalles ofte en «core-dump» siden datamaskinene for 20 40 år siden hadde hurtiglager bygget opp av ringer med kjerne av feritt. I UNIX heter denne filen derfor core. Forelesning 7.3.2001 Ark 7 av 36

maskin navn> /local/hacks/sgi/bin/ddd test-gdb & Forelesning 7.3.2001 Ark 8 av 36

I File-menyen finner vi «Open Core Dump». Forelesning 7.3.2001 Ark 9 av 36

Nå vet vi at feilen oppsto på linje 12 i forbindelse med *vec[i] = i. Kanskje det er noe galt med indeksen i? I Data-menyen finner vi «Display Local Variables» Forelesning 7.3.2001 Ark 10 av 36

Variabelen i er 0, så den er OK. Hva da med vec? Vikan klikke på en forekomst av vec og så «New Display». Forelesning 7.3.2001 Ark 11 av 36

Her ser vi at vec[0] er 0 mens vec[1] peker på noe; det burde vært omvendt! (vec[1] vec[9] skal ennå ikke ha fått noen verdi (siden i er 0).) Altså oppsto feilen under initieringen av vec der det står for (i = 0; i<10; ++i) { vec[1] = (int*)malloc(sizeof(int)); *vec[i] = i; } Vi kan da avslutte ddd med «Exit» i File-menyen. Forelesning 7.3.2001 Ark 12 av 36

Et eksempel til Følgende program skal skrive ut sine parametre og alle omgivelsesvariablene: #include <stdio.h> int main(int argc, char *argv[], char **envir) { char **p = envir, *e; int i; for (i = 0; i < argc; ++i) { printf("parameter %d: %s \n", i, argv[i]); } while (! (*p = NULL)) { e = *p; printf("%s\n", e); ++p; } return 0; } Kompilering går fint: maskin navn> cc -g printenv-feil.c -o printenv-feil men kjøringen går dårlig: maskin navn> printenv-feil a b Parameter 0: printenv-feil Parameter 1: a Parameter 2: b (null) (null). Control + \ Quit (core dumped) Forelesning 7.3.2001 Ark 13 av 36

Hva sier gdb/ddd? maskin navn> /local/hacks/sgi/bin/ddd printenv-feil & Forelesning 7.3.2001 Ark 14 av 36

Her ser vi imidlertid at feilen er oppstått i write, men den kaller vi da ikke i vårt program? Vi ber om «Backtrace» i Status-menyen. Forelesning 7.3.2001 Ark 15 av 36

Vi ser at feilen oppsto i linje 14 i main i kallet på printf. Vi klikker på «Up» fire ganger, og velger så «Display Local Variables» i Data-menyen. Vi ser at p ser OK ut, men e burde vel ikke være 0? La oss kjøre programmet på nytt, men legge inn et stoppunkt øverst i while-løkken. Pek og klikk på linjen, og så på «Break at ()». Så kan vi klikke på «Run» igjen. Forelesning 7.3.2001 Ark 16 av 36

Forelesning 7.3.2001 Ark 17 av 36

Etter at programmet er stoppet før det skal utføre while-løkken for første gang, lar vi det utføre de to første linjene ved å klikke på «Step». Forelesning 7.3.2001 Ark 18 av 36

Her ser vi at e er 0, og det må være galt! (Det var ihvertfall ikke det som var hensikten med programmet...) Dette skjedde i den gale testen while (! (*p = NULL)) { som burde vært skrevet while (*p!= NULL) { eller while (*p) { Konklusjon Et par timer brukt på å lære seg gdb og ddd kan man fort få mangedobbelt igjen for senere i kurset! Forelesning 7.3.2001 Ark 19 av 36

Andre feilsøkingverktøy Programmet lint Dette programmet sjekker C-programmer og rapporterer mulig feil og foreslår hvorledes koden kan forbedres. maskin navn> lint printenv-feil.c (12) warning: assignment operator "=" found where "==" was expected function returns value which is always ignored printf Kompilatormeldinger Noen ganger kan kompilatoren gi fornuftige advarsler om potensielle farer («warnings»). Egne meldinger Det aller beste er å regne med at man gjør feil og legge inn egne utskrifter som kan slås av og på ved behov. Forelesning 7.3.2001 Ark 20 av 36

Programmet purify Dette kommersielle programmet legger inn alle mulig tester som blir utført under kjøringen: maskin navn> purify cc test-gdb.c -o test-gdb Purify 4.1 IRIX6, Copyright (C) 1992-1997 Rational Software Corp.... Processing "/usr/lib/libc.so.1"... Processing "test-gdb" maskin navn> test-gdb Når feil oppstår, kommer et meldingsvindu: Forelesning 7.3.2001 Ark 21 av 36

Heltall I 8, 16 eller 32 bit kan vi lagre til dels store tall (med fortegns-bit): Bit Fra......til 8 128 127 16 32 768 32 767 32 2 147 483 648 2 147 483 647 Dette er imidlertid ikke alltid nok: Ett sekund er 9 192 631 770 perioder av strålingen... (Cesium 133). er et tall som er for stort for 32 bit. Dessuten kan vi trenge tall som ikke er heltall: Tallet π er 3,14159265... Forelesning 7.3.2001 Ark 22 av 36

Flyt-tall Tall kan skrives på flere forskjellige måter: 8 388 708 8,388708 10 6 8,39 10 6 De to siste ( M G E) er såkalte flyt-tall og består av: Mantisse («significand») (M). Grunntall («radix») (G). Eksponent (E). Fortegn. Forelesning 7.3.2001 Ark 23 av 36

Representasjon av eksponenten Man kan tenke seg flere ulike måter å lagre eksponenten på: 1. Eget fortegnsbit. 4 blir 1 0 0 0 0 1 0 0 2. 2-erkomplement. 4 blir 1 1 1 1 1 1 0 0 3. Fast tillegg (f.eks. 127 for 8 bits eksponent). 4 blir 0 1 1 1 1 0 1 1 (Dette kalles «excess 127» på engelsk.) Det siste velges oftest i dag. Det forenkler en del operasjoner på flyt-tall, f.eks. sammenlikning og sortering. Forelesning 7.3.2001 Ark 24 av 36

Representasjon av mantissen En desimal brøk: har desimaler. En binær brøk: 3,14159265 11,0010010 har binærer. Brøken tolkes slik: 2 1 Resultatet er 1 2 1 4 1 8 1 16 1 32 1 64 1 128 11,0010 0 1 0 2 1 + 2 0 + 2 3 + 2 6 = 2 + 1 + 1 8 + 1 64 3,1406 Forelesning 7.3.2001 Ark 25 av 36

En normalisert mantisse er en binær brøk med følgende egenskap: 1 M<G For binær representasjon innebærer dette at 1 M<2 Binæren foran binær-kommaet vil altså alltid være 1 (med mindre hele tallet er 0). Grunntallet Grunntallet er nesten alltid 2. Blir ikke lagret. Forelesning 7.3.2001 Ark 26 av 36

Standarden IEEE 754 for 32-bits flyt-tall 31 30 23 22 0 S Eksponent Mantisse S er fortegnet; 0 for positivt, 1 for negativt. Grunntallet er 2. Eksponenten er på 8 bit og lagres med fast tillegg 127. Mantissen er normalisert og på 24 bit, men kun de 23 etter binærkommaet lagres. Forelesning 7.3.2001 Ark 27 av 36

Hvordan lagres 1,0? 1,0 ti =1,0 to som er normalisert. Eksponent er 0+127=127=1111111 to. Fortegnet er 0. 31 30 23 22 0 0 01111111 00000000000000000000000 Hvordan lagres 0? Som spesialkonvensjon er 0 representert av kun 0-bit: 31 30 23 22 0 0 00000000 00000000000000000000000 Hvordan lagres 12,8125? 12,8125 ti = 1100,1101 to = 1,1001101 to 2 3 Eksponent er 3+127=130=10000010 to. Fortegnet er 1. 31 30 23 22 0 1 10000010 10011010000000000000000 Forelesning 7.3.2001 Ark 28 av 36

Største tall 31 30 23 22 0 0 11111110 11111111111111111111111 omtrent 2 254 127 2 3,4 10 38. (Eksponenten 0 er reservert for tallet 0, eksponenten 255 for NAN, «not a number».) Minste positive tall 31 30 23 22 0 0 00000001 00000000000000000000000 omtrent 2 1 127 1 1,2 10 38. Nøyaktighet Mantissen er på 24 bit, og 2 24 1,7 10 7. Dette gir 7 desimale sifre. Forelesning 7.3.2001 Ark 29 av 36

Standarden IEEE 754 for 64-bits flyt-tall Endringer: 63 62 52 51 0 S Eksponent Mantisse Eksponenten er økt fra 8 til 11 bit. Lagres med fast tillegg 1023. Mantissen er økt fra 24 til 53 bit. Øverste bit lagres stadig ikke. Forelesning 7.3.2001 Ark 30 av 36

Største tall Det største tallet som kan lagres, finner vi utfra formelen 2 (211 2) 1023 2 = 2 1023 2 1,8 10 308 Minste positive tall 2 1 1023 1 = 2 1022 1 2,2 10 308 Nøyaktighet Mantissen er på 53 bit, og 2 53 9,0 10 15. Dette gir nesten 16 desimale sifre. Forelesning 7.3.2001 Ark 31 av 36

Operasjoner på flyt-tall i MIPS I MIPS håndteres flyt-tall av en egen koprosessor med nummer 1. Den har sine egne registre $f0, $f1,..., $f31. En double opptar to registre; det første må ha et partallsnummer. Forelesning 7.3.2001 Ark 32 av 36

Flytting mellom CPU og flyt-tallsprosessoren Man må bruke egne instruksjoner for å flytte data mellom CPU-en og flyt-tallsprosessoren c1: mfc1 $x,$fy # c1 $fy CPU $x mtc1 $x,$fy # CPU $x c1 $fy Ved hjelp av to andre instruksjoner kan man lesefraogskrivetilram: lwc1 $fy,nn($x) # mem[nn+$x] c1 $fy swc1 $fy,nn($x) # c1 $fy mem[nn+$x] For double-verdier må man bruke to instruksjoner for å flytte. Forelesning 7.3.2001 Ark 33 av 36

Konvertering Instruksjonen cvt kan konvertere mellom d som er en double, s someren(«single»)float, eller w som er en long (eller int hvis den også er 32 bit, dvs et «word»). Eksempel cvt.d.w $fy,$fx # (long)$fx (double)$fx Aritmetiske operasjoner MIPS har de vanlige aritmetiske operasjonene: abs.x absoluttverdien. add.x addisjon. c.y.x sammenlign. div.x divisjon. mul.x multiplikasjon. neg.x negasjon. sub.x subtraksjon. x er enten d eller s. y er eq (=), le ( ) eller lt (<). Forelesning 7.3.2001 Ark 34 av 36

Ved sammenligning legges resultatet i et eget statusregister. Det kan testes med bc1f dit # Hopp dit hvis usant. bc1t dit # Hopp dit hvis sant. Funksjonskall Ved funksjonskall gjelder følgende: float-parametre legges i $f12 og $f14, double-parametre i $f12 $f13 og $f14 $f15. Ved mer enn to parametre, eller en kombinasjon av float og andre paramtre, følges en spesiell konvensjon. En float returverdi skal ligge i $f0. Forelesning 7.3.2001 Ark 35 av 36

Et eksempel fladd1 øker et 32-bits flyt-tall med 1: #include <regdef.h>.text.globl fladd1 # Navn: fladd1. # Synopsis: Øker en float med 1. # Signatur i C: float fladd1(float x); fladd1: li t0,1 # Hent verdien 1 mtc1 t0,$f0 # inn i $f0 og cvt.s.w $f0,$f0 # omdann til float. add.s $f0,$f0,$f12 # Addér x. jr ra # Retur. Testprogrammet test-fladd1.c #include <stdio.h> extern float fladd1(float x); int main(void) { float res = fladd1(3.14); printf("svaret er %.4f.\n", res); return 0; } Kompileringskommandoen maskin navn> cc test-fladd1.c fladd1.s -o test-fladd1 test-fladd1.c: fladd1.s: maskin navn> test-fladd1 Svaret er 4.1400. Forelesning 7.3.2001 Ark 36 av 36