IN 147 Program og maskinvare



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

IN 147 Program og maskinvare

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

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

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.

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

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

IN 147 Program og maskinvare

Programmeringsspråket C Del 3

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

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

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

IN 147 Program og maskinvare

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

Programmeringsspråket C Del 3. Michael Welzl

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

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

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

Del 4 Noen spesielle C-elementer

Oppgavene 1, 2, 4, 5, 6, 9, 12 og 13 passer best til å løses ved en datamaskin.

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.

Programmeringsspråket C Del 2

Del 1 En oversikt over C-programmering

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. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

Programmeringsspråket C Del 2

Programmeringsspråket C Del 2

Programmeringsspråket C

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

IN 147 Program og maskinvare

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

Signaturer. Dagens tema

Programmeringsspråket C

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

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

Kapittel 1 En oversikt over C-språket

Utførelse av programmer, metoder og synlighet av variabler i JSP

Programmeringsspråket C

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

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

En oppsummering (og litt som står igjen)

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

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

Cs preprosessor. Dagens tema. Betinget kompilering

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

TDT4102 Prosedyreog objektorientert programmering Vår 2016

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

INF109 - Uke 1b

Diverse eksamensgaver

INF1000 Metoder. Marit Nybakken 16. februar 2004

Rapport Semesteroppgave i datasikkerhet Harald Dahle (795955) og Joakim L. Gilje (796196)

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

Dagens tema: Enda mer MIPS maskinkode

Repetisjon fra sist - 1: Plan for dagen. Repetisjon fra sist 2: Hva jeg glemte sist: Nyttige Kommandoer

Programmeringsspråket C Del 2. Michael Welzl

Oblig 4 (av 4) INF1000, høsten 2012 Værdata, leveres innen 9. nov. kl

Tre måter å lese fra terminal. Java 4. Eksempel. Formatert utskrift til skjerm

Kompilering Statiske Syntaksanalyse Feilsjekking Eksempel Oppsummering

Øving 0 - Xcode TDT4102

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

2 Om statiske variable/konstanter og statiske metoder.

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

Dagens tema: INF2100. Syntaksanalyse. Hva annet gjør en kompilator? Sjekking av navnebruk. Testutskrifter

Dagens tema. Kort repetisjon om rutiner. Programmering i C Variable og adresser. Vektorer. Tekster. Preprosessoren. Separat kompilering

IN 147 Program og maskinvare. Dagens tema

<?php. count tar en array som argument, og returnerer et tall som uttrykker antallet innførsler i arrayen.

TDT4102 Prosedyre og Objektorientert programmering Vår 2014

Syntaksanalyse. Dagens tema: Språkdiagrammene Jernbanediagrammene er et ypperlig utgangspunkt for å analysere et program: INF2100 INF2100 INF2100

Dagens tema: Mer av det dere trenger til del 1

INF225 høsten 2003 Prosjekt del 4: kodegenerering

Kanter, kanter, mange mangekanter

Oppgave 1 JK-flip-flop (Total vekt 20%)

Debugging. Tore Berg Hansen, TISIP

Hvordan en prosessor arbeider, del 1

Dagens tema: Datastrukturer

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema. Hva er kompilering? Anta at vi lager dette lille programmet doble.rusc (kalt kildekoden): Hva er kompilering?

Dagens tema: Kjøresystemer II

Dagens tema: 12 gode råd for en kompilatorskriver

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

Innhold uke 4. INF 1000 høsten 2011 Uke 4: 13. september. Deklarasjon av peker og opprettelse av arrayobjektet. Representasjon av array i Java

TDT4102 Prosedyre og Objektorientert programmering Vår 2015

Oversikt. INF1000 Uke 1 time 2. Repetisjon - Introduksjon. Repetisjon - Program

Løse reelle problemer

Kontinuasjonseksamen

Oversikt. INF1000 Uke 2. Repetisjon - Program. Repetisjon - Introduksjon

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

Prosesser. Dagens tema. Hva er en prosess? En prosess er et program under utførelse.

Høgskolen i Gjøvik Institutt for informatikk og medieteknikk E K S A M E N. Grunnleggende programmering

INF1000 (Uke 5) Mer om løkker, arrayer og metoder

Transkript:

Dagens tema Deklarasjon av nye typer Typekonvertering Regning med pekere Pekere til funksjoner Pekere til pekere til... Vanlige feil ved bruk av pekere Feilsøking Debuggere lint Kompilatormeldinger Egne testutskrifter Ark 1 av 24 Forelesning 3.3.1999

Deklarasjon av nye typer I C kan vi definere nye typer: typedef unsigned char uc; uc c1, ctab[10]; Typedefinisjoner brukes til å unngå lange navn: uc kontra unsigned char punkt kontra struct punkt definisjoner som kan variere fra ett system til et annet; for eksempel i stdlib.h på en SGI: typedef unsigned int size_t; Typen size t brukes som type for en størrelse. Forelesning 3.3.1999 Ark 2 av 24

Typekonvertering Noen ganger må vi angi en eksplitt typekonvertering: (type)verdi Følgende program runder av beløp til nærmeste 50-øring: #include <stdio.h> int main(void) { double kr, krx; printf("gi et beløp: "); scanf("%lf", &kr); while (kr >= 0.0) { krx = (int)(2*kr+0.5) / 2.0; /* Rund av */ printf("%.4lf blir %.4lf\n", kr, krx); printf("gi et beløp: "); scanf("%lf", &kr); Eksempel på en kjøring: 2.0000 blir 2.0000 2.1000 blir 2.0000 2.2400 blir 2.0000 2.4500 blir 2.5000 2.7500 blir 3.0000 Forelesning 3.3.1999 Ark 3 av 24

Typekonvertering mellom tall Typekonvertering brukes mellom ulike heltall og/eller flyt-tall. Typekonvertering mellom pekere Siden pekere i prinsippet kan være av ulikt antall bit, skal man egentlig angi konvertering mellom dem. (Dette hjelper også kompilatoren å finne feil.) Pekertypen void* er garantert stor nok til alle pekere, og kan derfor betraktes som en «peker til alt mulig». Funksjonen malloc er derfor definert som void *malloc (size_t size) Korrekt bruk av malloc er derfor xxx *p; : p=(xxx*)malloc(sizeof(xxx); Forelesning 3.3.1999 Ark 4 av 24

Regning med pekere I C gjelder alltid at a[i] *(a+i) Dette er greit om a er en char-vektor, men hva om den er en long? Egne regneregler for pekere I C gjelder egne regneregler for pekere: p+i betyr «Øk p med i multiplisert med størrelsen av det p peker på.» #include <stdio.h> typedef unsigned long ul; int main(void) { char *cp = (char*)0x123400; long *lp = (long*)0x123400; cp++; lp++; printf("cp = 0x%lx\nlp = 0x%lx\n", (ul)cp, (ul)lp); gir følgende når det kjøres: cp = 0x123401 lp = 0x123404 Forelesning 3.3.1999 Ark 5 av 24

Pekere til funksjoner Det er nyttig å kunne behandle funksjoner som om de var variable, og noen høynivåspråk tilbyr dette. C tilbyr noe som er nesten like godt: pekere til funksjoner. #include <stdio.h> int sum(int (*f)(int x), int n) { /* Beregn summen av f(x) for x=1,...,n. */ int res = 0, ix; for (ix = 1; ix <= n; ++ix) res += f(ix); return res; Her er parameteren f en peker til en funksjon: Denne funksjonen returnerer en int. Denne funksjonen har én parameter: en int. Forelesning 3.3.1999 Ark 6 av 24

Bruk av funksjonspekere Bruk av et funksjonsnavn uten parenteser bak, gir en peker til funksjonen. (Dette implementeres som adressen til første instruksjon i funksjonen.) int odd(int x) /* Er x et oddetall? */ { return x%2; int sqr(int v) /* Finn kvadratet av v. */ { return v*v; int main(void) { printf("sum av odd(n): %5d\n", sum(odd,10)); printf("sum av sqr(n): %5d\n", sum(sqr,10)); Kjøring av dette lille programmet gir følgende resultat: Sum av odd(n): 5 Sum av sqr(n): 385 Forelesning 3.3.1999 Ark 7 av 24

Pekere til pekere til... Noen ganger trenger man en peker til en pekervariabel (for eksempel fordi den skal overføres som parameter og endres). Siden vanlige pekere deklareres som xxx *p; må en «peker til en peker» angis som xxx **pp = &p; Dette kan utvides med så mange stjerner man ønsker. Eksempel Omgivelsesvariable i UNIX inneholder opplysninger om en bruker og hans eller hennes preferanser: LOGNAME=dag PAGER=less HOSTTYPE=sgi PRINTER=prent HOME=/home/ansatte/03/dag SHELL=/local/gnu/bin/bash Forelesning 3.3.1999 Ark 8 av 24

Omgivelsen overføres fra program til program ved en tredje parameter til main: int main(int argc, char *argv[], char **envir) Parameteren envir peker på en vektor av pekere som hver peker på en omgivelsesvariabel og den definisjon. LOGNAME=dag envir 0 PAGER=less HOSTTYPE=sgi PRINTER=prent HOME=/home/ansatte/03/dag SHELL=/local/gnu/bin/bash Forelesning 3.3.1999 Ark 9 av 24

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 «flyte rundt» og oppta plass så lenge programmet kjører. Dette kalles en hukommelseslekkasje. Forelesning 3.3.1999 Ark 10 av 24

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 3.3.1999 Ark 11 av 24

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]); Forelesning 3.3.1999 Ark 12 av 24

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 3.3.1999 Ark 13 av 24

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. For å bruke gdb må vi gjøre to ting: kompilere våre programmer med opsjonen -g, og angi at vi ønsker programdumper: ulimit -c unlimited hvis vi bruker bash. (Da må vi huske å fjerne programdumpfilene selv; de er store!) Forelesning 3.3.1999 Ark 14 av 24

Programdumper Når et program dør på grunn av en feil («aborterer»), prøver det ofte å skrive innholdet av hele prosessen på 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-r--r-- 1 dag dag 136284 Mar 1 13:28 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 3.3.1999 Ark 15 av 24

1. gdb startes: maskin navn> gdb test-gdb GNU gdb 4.17 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "mips-sgi-irix6.2"... (gdb) 2. Vi ber om analyse av programdumpen: (gdb) core-file core Core was generated by test-gdb. Program terminated with signal 11, Segmentation fault. Reading symbols from /usr/lib/libc.so.1...done. (gdb) #0 0x400abc in main () at test-gdb.c:12 12 *vec[i] = i; Forelesning 3.3.1999 Ark 16 av 24

Nå vet vi at feilen oppsto på linje 12 i forbindelse med *vec[i] = i. Kanskje det er noe galt med indeksen i? (gdb) print i $1=0 (gdb) Variabelen i er 0, så den er OK. Hva da med vec? (gdb) print vec $2 = {0x0, 0x10002010, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 (gdb) 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 gdb: (gdb) quit Forelesning 3.3.1999 Ark 17 av 24

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; 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) (null). Control + \ Quit (core dumped) Forelesning 3.3.1999 Ark 18 av 24

Hva sier gdb? maskin navn> gdb printenv-feil core GNU gdb 4.17 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "mips-sgi-irix6.2"... Core was generated by printenv-feil. Program terminated with signal 3, Quit. Reading symbols from /usr/lib/libc.so.1...done. #0 0xfa43acc in _write () at write.s:15 write.s:15: No such file or directory. Adressefeilen oppsto altså i write, men den kaller ikke vi. Hvilke funksjoner har vært kalt? Forelesning 3.3.1999 Ark 19 av 24

(gdb) backtrace #0 0xfa43acc in _write () at write.s:15 #1 0xfa3c6a4 in _xflsbuf () at flush.c:89 #2 0xfa378cc in _doprnt () at doprnt.c:186 #3 0xfab52ac in printf () at printf.c:42 #4 0x400a28 in main (argc=1, argv=0x7fff2f14, envir=0x7fff2f1c) at printenv-feil.c:14 #5 0x400938 in start () at crt1text.s:165 Vi vil se mer på innmaten i main, så vi går 4 kall tilbake: (gdb) up 4 #4 0x400a28 in main (argc=1, argv=0x7fff2f14, envir=0x7fff2f1c) at printenv-feil.c:14 14 printf("%s\n", e); Forelesning 3.3.1999 Ark 20 av 24

Utifra utskriften er det naturlig å anta at feilen ligger i løkken i linje 12 16, så den bør nok sjekkes nærmere. Sett inn et stoppunkt i linje 12 og la programmet gå dit: (gdb) break 12 Breakpoint 1 at 0x4009f0: file printenv-feil.c, line 12. (gdb) run Starting program: /home/ansatte/03/dag/in147/forelesninger/kode/printenv-feil Parameter 0: /home/ansatte/03/dag/in147/forelesninger/kode/printenv-feil Breakpoint 1, main (argc=1, argv=0x7fff2f14, envir=0x7fff2f1c) at printenv-feil.c:12 12 while (! (*p = NULL)) { Sjekk p og *p: (gdb) print p $1 = (unsigned char **) 0x7fff2f1c (gdb) print *p $2 = (unsigned char *) 0x7fff303c "LOGNAME=dag" Forelesning 3.3.1999 Ark 21 av 24

Alt ser fint ut foreløbig. Utfør to linjer til og sjekk hva e er blitt: (gdb) next 13 e = *p; (gdb) next 14 printf("%s\n", e); (gdb) print e $3 = (unsigned char *) 0x0 Her er feilen! Hva er p og *p nå? (gdb) print p $4 = (unsigned char **) 0x7fff2f1c (gdb) print *p $5 = (unsigned char *) 0x0 *p er blitt 0! Dette skjedde i den gale testen while (! (*p = NULL)) { som burde vært skrevet while (*p!= NULL) { eller while (*p) { Forelesning 3.3.1999 Ark 22 av 24

Konklusjon Noen timer brukt på å lære seg gdb får man mangedobbelt igjen senere i kurset! Mer informasjon om gdb Dokumentasjon om gdb finnes følgende steder: Når man har startet gdb, kan man gi kommandoen help. Kommandoen «man gdb» gir en kortfattet oversikt. Filen /local/doc/gnu/gdb-refcard.ps gir en to-siders oversikt over kommandoene i gdb. Filen /local/doc/gnu/gdb.dvi er den fulle dokumentasjonen av gdb; den er på 200 sider. Forelesning 3.3.1999 Ark 23 av 24

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 function falls off bottom without returning value (17) main function returns value which is always ignored printf Kompilatormeldinger Noen ganger kan kompilatoren gi fornuftige advarsler om potensielle farer hvis man ber om det: maskin navn> cc -fullwarn printenv-feil.c Egne meldinger Det beste er å legge inn egne utskrifter som kan slås av og på ved behov. Forelesning 3.3.1999 Ark 24 av 24