GCC Uvod ⇀ GNU Toolchain ⇀ Šta je GCC? ⇀ Arhitektura GCC-a ⇀ Kako instalirati GCC? Kompilacija programa ⇀ Prevođenje fajlova sa različitim ekstenzijama ⇀ Faze kompilacije Primer ⇀ Kompilacija u jednom koraku ⇀ Kompilacija u nekoliko koraka Jezički standardi podržani od strane GCC-a ⇀ Programski jezik C ⇀ Programski jezik C++ Opcije komandne linije ⇀ Pretprocesiranje ⇀ Povezivanje ⇀ Traženje i suzbijenje upozorenja ⇀ Otklanjanje grešaka ⇀ Optimizacija





GCC

Kao početnici u svetu programskih jezika i računara trebalo bi da budemo svesni da računari ne mogu da razumeju nijedan od programskih jezika sa kojima radimo. Mogu da tumače samo mašinski jezik nula i jedinica. Kompajler nam ovde priskače u pomoć. U ovom poglavlju upoznaćemo se sa opštim konceptima GCC kompajlera.

Uvod

GNU Toolchain

GNU lanac alata je široka kolekcija programskih alata proizvedenih od strane GNU projekta. Ovi alati zapravo čine skup alata koji je koristi na serijski način za razvoj softverskih aplikacija i operativnih sistema.

GNU Toolchain sadrži:
  ● GCC Compiler Collection
  ● GNU Make
  ● GNU Binutils
  ● GNU Debugger
  ● GNU Autotools
  ● GNU Bison

Šta je GCC?

GCC je integrisana distribucija kompajlera za nekoliko glavnih programskih jezika: C, C++, Objective-C, Objective-C++, Fortran, Ada, D i GO. On prevodi programske jezike na mašinski jezik, tj. konvertuje izvorni kod u izvršnu datoteku instrukcija za računare. Proizveden je u okviru GNU projekta. Osim što je zvanični kompajler GNU sistema, usvojen je kao standardni kompajler većine modernih operativnih sistema baziranih na Unix-u, uključujuci Linux, BSD i Mac OS X.

Prva verzija GCC-a, GCC 1.0, objavljena je 1987. godine.

Skraćenica GCC ima višestruko značenje:
  ● GNU Compiler Collection - odnosi se na kompletan skup alata
  ● GNU C Compiler - koristi se kada je naglasak na kompajliranju C programa
  ● komponenta GCC nezavisna od jezika - kod koji se deli među kompajlerima za sve podržane jezike

Arhitektura GCC-a

Svaki kompajler sastoji se od 3 komponente:
  ● prednji kraj - razlikuje se za različite programske jezike
  ● srednji kraj
  ● zadnji kraj - razlikuje se za različite arhitekture

GCC kompajlira jednu po jednu datoteku tako što izvorni kod prolazi kroz sve 3 komponente, redom.
Deo GCC-a nezavisan od jezika uključuje većinu optimizatora, kao i pozadinske komponente koje generišu mašinski kod za različite procesore.
Pored prednjih krajeva koji su integrisane komponente GCC-a, postoji nekoliko drugih prednjih krajeva koji se održavaju odvojeno. Oni podržavaju jezike kao što su Mercuri i COBOL. Da bi ih koristili, moraju biti izgrađeni zajedno sa GCC-om.

Kako instalirati GCC?

Da biste koristili GCC morate proveriti da li je instaliran na vašem sistemu. To možete uraditi komandom:

$ gcc --version
Ako jeste, dobićete poruku o broju verzije i autorskim pravima na standardni izlaz. Ubuntu 20.04 obezbeđuje 9.3.0 GCC verziju pa u tom slučaju dobijate sledeće:

gcc (Ubuntu 9.3.0-10ubuntu2)
9.3.0Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Podrazumevani Ubuntu repozitorijumi sadrže meta-paket pod nazivom build-essential koji uključuje GNU kompajler, GNU debager (više o njemu biće reči na samom kraju kursa) i druge razvojne biblioteke i alate potrebne za kompajliranje softvera.
Da biste instalirali pakete razvojnih alata, pokrenite sledeću komandu kao root ili korisnik sa sudo privilegijama:

$ sudo apt update
$ sudo apt install build-essential
Komanda instalira dosta paketa među kojima su gcc, g++ i make.
Da biste bili sigurni da li je GCC kompajler uspešno instaliran možete ponovo pokrenuti komandu za proveru verzije.
Dokumentaciju o GCC-u možete dobiti pomoću sledećih komandi:

$ man gcc
$ info gcc

Kompilacija programa

Ukoliko se C program nalazi u fajlu fajl.c, prevodilac možete jednostavno pozvati komandom:

$ gcc fajl.c
U ovom slučaju rezultat kompajliranja će biti izvršni fajl sa generičkim imenom a.out.
Izvršni fajl možete pokrenuti pomoću sledeće komande koja poziva fajl sa nazivom a.out iz tekućeg direktorijuma:

$ ./a.out
Ukoliko želite dodeliti alternativno ime izvršnom fajlu, to se može omogućiti pomoću parametra -o (output):

$ gcc  -o  ime_izvršnog_fajla fajl.c
Tada izvršni fajl možete pokrenuti na sličan način, korišćenjem sledeće komande koja poziva fajl sa nazivom ime_izvršnog_fajla iz tekućeg direktorijuma:

$ ./ime_izvršnog_fajla
Takodje, možete smestiti izvršni fajl u određeni folder na računaru tako što ćete navesti putanju:

$ gcc  -o  ~/bin/fajl

Prevođenje fajlova sa različitim ekstenzijama

S obzirom da GCC predstavlja kolekciju prevodioca, koji će prevodilac biti pokrenut određuje se ne osnovu ekstenzije fajla.

.h C datoteka zaglavlja (ne treba da se kompajlira ili poveže)
.c C izvorni kod koji mora da se pretprocesira
.i C izvorni kod koji ne treba da se pretprocesira
.ii C++ izvorni kod koji ne treba da se pretprocesira
.cc, .cp, .cxx, .cpp, .c++, .c C++ izvorni kod koji mora da se pretprocesira
.m Objective-C izvorni kod
.mi Objective-C izvorni kod koji ne treba da se pretprocesira
.mm, .M Objective-C++ izvorni kod koji mora da se pretprocesira
.mii Objective-C++ izvorni kod koji ne treba da se pretprocesira
.f, .for, .FOR Fortran izvorni kod koji ne treba da se pretprocesira
.F, .fpp, .FPP Fortran izvorni kod koji mora da se pretprocesira (tradicionalinim pretprocesorom)
.r Fortran izvorni kod koji mora da se pretprocesira RATFOR pretprocesorom koji se ne nalazi u sklopu GCC-a
.go GO izvorni kod
.d D izvorni kod
.s Asemblerski kod
.S, .sx Asemblerski kod koji mora da se pretprocesira

Korišćenjem opcije -x možete eksplicitno navesti jezik ulaznog fajla. Ona kao argument ima identifikator jezika za koji će prevodilac biti pozvan. Neki od argumenata dati su u tabeli:

programski jezik kompajler identifikator
C gcc c
C++ g++ c++
Objective-C gcc objective-c
Objective-C++ gcc objective-c++
Fortran g77 f77
Ada gnat ada
D dmd d

Ukoliko je neki C program smesten u fajl sa imenom fajl.code, naredba za njegovo prevođenje glasila bi:

$ gcc  -x c  fajl.code

Faze kompilacije

Moguće je posebno kompajlirati i povezivati izvršni fajl:

$ gcc -c fajl.c   // kao rezultat se dobija fajl.o
$ gcc -o fajl fajl.o   // kao rezultat se dobija fajl
GCC proces kompilacije se zapravo sastoji iz više koraka od kojih se svaki može izvršiti posebno:

● Pretprocesiranje (preprocessing)
Ovo je nulta faza kompilacije u kojoj se vrši elementarna obrada izvornog koda:
  ⇀uključivanje datoteka zaglavlja i spajanje svih ulaznih datoteka u jedinicu prevođenja (compilation unit)#include
  ⇀ekspanzija makroa #define
  ⇀uklanjanje komentara //
● Kompilacija u užem smislu (compilation)
Od jedinice prevođenja generiše se asemblerski kod.
● Asembliranje (assembeling)
Asemblerski kod konvertuje se u objektni kod na mašinskom jeziku.
● Povezivanje (linking)
Objektni kod dobijen kompilacijom pojedinačnih modula se korišćenjem programa koji se naziva povezivač (linker) povezuje sa objektnim kodom statičkih biblioteka čime se dobija jedinstven izvršivi program (executable file).

U poslednje 2 faze, pored GCC-a koriste se i GNU Binutils binarni alati. To je skup programskih alata za kreiranje i upravljanje binarnim programima, objektnim fajlovima, bibliotekama, itd.
  ⇀as - GNU Assembler
  ⇀ld - GNU Linker

Proces kompilacije C/C++ programa prikazan je šematski na sledećoj slici:

kompiliranje


Primer

Neka je dat jednostavam “Hello World” C program koji se nalazi u hello.c fajlu i samo ispisuje poruku u terminalu:

#include <stdio.h>
int main() {
  printf(“Hello World\n”);
  return 0;
}

Kompilacija u jednom koraku

Sledeća komanda vrši kompilaciju u jednom koraku, pri čemu se dobija izvršni fajl a.out:

$ gcc hello.c
Ako želite da dobijete izvršni fajl pod nazivom hello, to možete uraditi opcijom -o:

$ gcc -o hello hello.c

Kompilacija u nekoliko koraka

Svaku od faza kompilacije možete izvršiti pojedinačno:

  1. pretprocesiranje
$ gcc -E hello.c -o hello.i
  2. kompilacija
$ gcc -S hello.i
  3. asembliranje
$ gcc -c hello.s
  4. linkovanje
$ gcc -o hello hello.o

Jezički standardi podržani od strane GCC-a

Za svaki podržani jezik GCC pokušava da prati jednu ili više standardnih verzija. Po potrebi možete koristiti opcije za navođenje standarda sa kojim će GCC biti usklađen prilikom kompilacije.
Dodatno, da biste dobili svu dijagnostiku za kršenje ograničenja i pravila sintakse, trebalo bi da navedete -pedantic ili -pedantic-errors ukoliko želite da upozorenja budu prikazana kao greške.

U nastavku govorićemo o istoriji standarda C-a i C++-a, kao i o komandnim opcijama za njihovo korišćenje.

Programski jezik C

Podrazumevani jezički standard za programski jezik C je gnu11, što je C11 standard sa GNU specifičnim ekstenzijama.

● C89 je prvi zvanični C standard koji je ANSI objavio 1989. godine.
Razlikovao se od neformalnog K&R C standarda po sledećim funkcionalnostima:
  ⇀ prototipi funkcija
  ⇀ podrška za void pokazivače koji moraju biti kastovani da bi se pristupilo podacima
  ⇀ podrška za međunarodni skup znakova
  ⇀ poboljšanje deklaracije parametara funkcije
  ⇀
● C90 je ISO verzija standarda koja opisuje potpuno isti jezik kao C89. ANSI je zvanično usvojio ISO verziju standarda.
● C94 / C95 je bio amandman na C90, dodajući nekoliko karakteristika, uglavnom digrafe i široku podršku karaktera.
● C99 je ISO objavio 1999. Dodat je veliki broj novih funkcionalnosti:
  ⇀ inline funkcije (prednost u odnosu na makroe jer omogućavaju proveru tipova)
  ⇀ nizovi promenljive dužine gde je dužina niza izraz vremena izvršavanja
  ⇀ ključna reč restrict koja se koristi u deklaracijama pokazivača kao kvalifikator tipa za pokazivače
  ⇀ jednolinijski komentari koji počinu sa // kao u C++-u
  ⇀ generičke matematičke funkcije
  ⇀ složeni literali za strukture i nizove
  ⇀ promenljivi broj argumenata za makroe (varijabilni makroi)
  ⇀ podrška za univerzalni skup znakova za imena
  ⇀ novi tipovi podataka: long long int, bool, complex
  ⇀ podrška za tipove celih brojeva specifične za implementaciju
  ⇀ podrška za pokretni zarez uključuje IEEE 754-1985 ili IEC 60559 definicije s pokretnim zarezom koje odgovaraju hardverskoj podršci koju ima većina mikroprocesora
  ⇀ nove bibliotečke funkcije: snprintf
  ⇀ nove standardne datoteke zaglavlja: stdbool.h (logički tip), complex.h (kompleksni brojevi), tgmath.h (matematika) i inttipes.h (novi celogbrojni tipovi)
  ⇀
● C11 je ISO izdao 2011. C11 je nastojao da se pozabavi problemima C99 i da se bliže uskladi sa C++ standardom, C++11. On menja neke potrebne funkcije C99 u opcione. Dodaci se takođe mapiraju u C++11 karakteristike koje olakšavaju povezivanje C i C++ koda:
  ⇀ podrška za Unicode karaktere
  ⇀ usaglašena podrška za IEC 60559 aritmetiku sa pokretnim zarezom
  ⇀ podrška za višenitno programiranje
  ⇀ anonimne strukture i unije
  ⇀ nove ključne reči: alignas (prefiks za označavanje promenljivog poravnanja) i alignof (vraća poravnanje u bajtovima za dati tip)
  ⇀ poboljšanje bibliotečkih funkcija za manipulaciju sa stringovima: strcat_s, strncpi_s (imaju dodatni parametar veličine koji se koristi za ograničavanje operacija stringova tako da nedostajući null terminator ne dozvoljava funkcijama da pređu kraj bafera)
  ⇀

C standard komandna opcija
C89 / C90 -ansi, -std=c89, -std=c90, -std=iso9899:1990
C94 -std=iso9899:199409
C99 -std=c99, -std=iso9899:1999
C11 -std=c11, -std=iso9899:2011
C17 -std=c17, -std=iso9899:2017

Programski jezik C++

GCC podržava originalni ISO C++ standard objavljen 1998. godine i revizije iz 2011, 2014, 2017. i veći deo revizije iz 2020.

● C++98 je prva verzija ISO C++-a.
● C++03 je skoro identičan C++98. Najvažnija razlika ogleda se u tome što je C++03 uveo inicijalizaciju vrednosti.
● C++11 je bio značajna revizija jezika. Dodato je sledeće:
  ⇀ standardizovana semantika za višenitno programiranje
  ⇀ rvalue reference
  ⇀ pametni pokazivači
  ⇀ semantika kretanja
  ⇀ petlje zasnovane na opsegu
  ⇀ lambda funkcije
  ⇀ heš tabele
  ⇀ novi tipovi: auto, decltype
  ⇀
● C++14 ima nekoliko poboljšanja u poređenju sa C++11:
  ⇀ generalizovane lamda funkcije
  ⇀ proširenje povratnog tipa na sve funkcije
  ⇀ omogućavanje mnogo više konstrukcija da se pojave u funkcijama constexpr
  ⇀
● C++17 je napravio velike promene u jeziku. Neke nove karakteristike jezika jezgra koje pojednostavljuju mnoge uobičajene konstrukcije uključuju:
  ⇀ poboljšanje lambda funkcija
  ⇀ istovremeni i paralelni algoritmi u biblioteci standardnih šablona (STL)
  ⇀ ugnježdeni prostori imena
  ⇀ inicijalizacija u if-u i switch-u
  ⇀ nove biblioteke: std::variant i std::opcional
  ⇀
● C++20 obezbedio je sledeće funkcionalnosti:
  ⇀ korutine
  ⇀ koncepti
  ⇀ naznačeni inicijalizatori
  ⇀ sintaksa šablona za lambda funkcije
  ⇀ tipovi klasa u parametrima šablona koji nemaju tip
  ⇀ constexpr virtuelne funkcije
  ⇀ neposredne funkcije
  ⇀ korišćenje enum-a
  ⇀ sinhronizovani baferovani izlazni tok
  ⇀ nove biblioteke: std::span, std::numbers (matematičke konstante), std::is_constant_evaluated, std::bit_cast, std::midpoint, std::to_array
  ⇀

C++ standard komandna opcija za standardu verziju komandna opcija za proširenu verziju
C++98, C++03 -ansi, -std=c++98, -std=c++03 -std=gnu++98
C++11 -std=c++11 -std=gnu++11
C++14 -std=c++14 -std=gnu++14
C++17 -std=c++17 -std=gnu++17
C++20 -std=c++20 -std=gnu++20

Opcije komandne linije

Većina opcija komandne linije koje možete koristiti sa GCC-om su korisne za C programe.
Možete mešati opcije i druge argumente. Uglavnom, redosled koji koristite nije bitan. Redosled je bitan samo ukoliko koristite nekoliko opcija iste vrste. Neke opcije uzimaju jedan ili više argumenata koji su obično odvojeni ili razmakom ili znakom jednakosti koji potiče iz naziva opcije.

Pretprocesiranje

Ove opcije kontrolišu C pretprocesor, koji se pokreće na svakoj C izvornoj datoteci pre stvarne kompilacije. Imaju smisla samo zajedno sa -E opcijom jer uzrokuju da izlaz pretprocesora bude neprikladan za stvarnu kompilaciju.

komandna opcija opis komandne opcije
-D ime Makrou ime dodeljuje se vrednost 1.
-D ime=definicija Makrou ime dodeljuje se vrednost 1.
-U ime Uklanja definiciju makroa ime dodeljenu opcijom -D.
-include fajl Obrađuje datoteku kao da se #include fajl pojavio kao prvi red primarne izvorne datoteke. Ako je dato više -include opcija, fajlovi se uključuju u redosledu u kome su navedeni u komandnoj liniji.
-imacros fajl Radi isto kao i -include, s tim što se svaki izlaz proizveden skeniranjem datoteke odbacuje. Makroi koje definiše ostaju definisani. Omogućava da preuzmete sve makroe iz zaglavlja bez obrade njihovih deklaracija.
Sve datoteke navedene sa -imacros se obrađuju pre svih datoteka navedenih sa -include.
-H Štampa listu svih korišćenih datoteka zaglavlja.
-undef Obezbeđuje da standardni makroi budu definisani i da se ne mogu predefinisati.

Povezivanje

Sledeće opcije korisne su kada kompajler povezuje objektne datoteke u izvršnu datoteku. Besmislene su ukoliko kompajler ne vrši korak povezivanje.

komandna opcija opis komandne opcije
-flinker-output=type Kontroliše generisanje koda optimizatora vremena povezivanja.
-fuse-ld=bfd Umesto podrazumevanog koristi bfd linker.
-fuse-ld=gold Umesto podrazumevanog koristi gold linker.
-fuse-ld=lld Umesto podrazumevanog koristi lld linker.
-l Nakon nje se, bez blanko znakova, navodi bibliotka koja se dodaje ili putanja do nje.
-L Nakon nje se, bez blanko znakova, navodi datoteke zaglavlja koja se dodaje ili putanja do nje.
-nostartfiles Prilikom povezivanja ne koriste se standardne datoteke za pokretanje sistema prilikom povezivanja.
-nodefaultlibs Prilikom povezivanja ne koriste se standardne sistemske biblioteke prilikom povezivanja. Povezivaču se prosleđuju samo one biblioteke koje navedete.
-nolibc Prilikom povezivanja ne koristi C biblioteku i sistemske biblioteke vezane za nju.
-nostdlib Prilikom povezivanja ne koristi standardne datoteke za pokretanje sistema i biblioteke.
-pie Proizvodi dinamički povezanu izvršnu datoteku nezavisnu od pozicije na ciljevima koji je podržavaju. Za predvidljive rezultate morate da navedete isti skup opcija koje se koriste za kompilaciju (-fpie, -fPIE ili podopcije modela).
-no-pie Ne proizvodi dinamički povezanu izvršnu datoteku nezavisnu od pozicije.
-static-pie Proizvodi izvršnu datoteku nezavisnu od statične pozicije na ciljevima koji ga podržavaju. Izvršni fajl nezavisno od statičkog položaja sličan je statičkom izvršnom fajlu, ali se može učitati na bilo kojoj adresi bez dinamičkog povezivača. Za predvidljive rezultate morate navedesti isti skup opcija koje se koriste za kompilaciju (-fpie, -fPIE ili podopcije modela).
-r Proizvodi pokretni objekat kao izlaz. Ovo je poznato i kao delimično povezivanje.
-s Uklanja sve tabele simbola i informacije o premeštanju iz izvršne datoteke.

Traženje i suzbijenje upozorenja

GCC pored poruka o sintaksnim greškama (u slučaju čijeg postojanja ne biva generisan izvršni fajl) može da generiše i poruke o upozorenjima na konstrukcije koje su sintaksno ispravne, ali liče na semantički neispravne. Neka upozorenja dostupna su i bez uključivanja dodatnih opcija. Šta će sve biti prijavljeno kao upozorenje određuje se opijama koje imaju prefiks -W:

$ gcc  -W  fajl.c
Napomena: Obratite pažnju na veliko W !!!

Najveći broj bitnih konstrukcija biće prijavljivan ako zadate grupnu opciju -Wall. Neke od opcija koje bivaju uključene sa -Wall su:

komandna opcija opis komandne opcije
-Wchar-subscripts Upozorava ako indeks niza ima tip char. Ovo je čest uzrok greške, jer programeri često zaboravljaju da je ovaj tip signed na nekim mašinama.
-Wcomment Upozorava kada se sekvenca za početak komentara '/*' pojavi u komentaru '/*', ili kada se u komentaru '//' pojavi obrnuta kosa crta-novi red.
-Wformat Proverite pozive funkcija kaošto su printf i scanf da biste bili sigurni da dostavljeni argumenti imaju tipove koji odgovaraju navedenom nizu formata i da konverzije navedene u stringu imaju smisla. Ovo uključuje standardne i druge funkcije određene atributima formata.
-Wnonnull Upozorava na prosleđivanje null pokazivača za argumente koji zahtevaju vrednost koja nije null. Može se onemogućiti opcijom -Wno-nonnull.
-Winit-self Upozorava na neinicijalizovane promenljive koje su inicijalizovane same sobom. Imajte na umu da se ova opcija može koristiti samo sa opcijom -Wuninitialized, koja radi samo sa opcijama -O1 i iznad.
-Wimplicit-int Upozorava kada deklaracija ne navodi tip.
-Wimplicit-function-declaration Upozorava ako je funkcija korišćena pre nego što je deklarisana.
-Wmain Upozorite ako je tip main-a sumnjiv. Main bi trebalo da bude funkcija sa spoljnim povezivanjem koja vraća int, uzimajući nula, dva ili tri argumenta odgovarajućeg tipa.
-Wmissing-braces Upozorava ako inicijalizator agregata ili unije nije u potpunosti u zagradama.
-Wmissing-include-dirs Upozorava ako direktorijum uključivanja koji je dostavio korisnik ne postoji.
-Wreturn-type Upozorava kad god je funkcija definisana povratnim tipom koji je podrazumevano postavljen na int. Takođe upozorite na bilo koju povratnu naredbu bez povratne vrednosti u funkciji čiji povratni tip nije void.
-Wswitch Upozorava kad god naredba svitch ima indeks nabrojivog tipa i nema velika i mala slova za jedan ili više imenovanih kodova te enumeracije. Oznake slučaja van opsega nabrajanja takođe izazivaju upozorenja kada se koristi ova opcija.
-Wunused-function Upozorava kad god je statička funkcija deklarisana, ali nije definisana ili se neugrađena statička funkcija ne koristi.
-Wunused-label Upozorava kad god je labela definisana, ali se ne koristi.
-Wunused-variable Upozorava kad god se lokalna promenljiva ili nekonstantna statička promenljiva ne koristi osim u svojoj deklaraciji.
-Wunused-value Upozorava kad god se neka izračunata vrednost ne koristi.
-Wuninitialized Upozorava ako se automatska promenljiva koristi bez prethodne inicijalizacije ili ako promenljiva može biti blokirana pozivom setjmp. Ova upozorenja su moguća samo u optimizaciji kompilacije, pa ih nema smisla koristiti bez neke od -O* opcija.

Grupna opcija -Wextra podržava više upozorenja od -Wall, a opcijom -Werror sva upozorenja prijavljuju se kao greške.

Takođe, opcija -Werror= pretvara upozorenje navedeno posle znaka jednakosti u grešku. Ova opcija ima i negativan oblik koji se koristiti za negiranje -Werror za određena upozorenja.
Na primer -Werror=switch pretvara upozorenja koja kontroliše -Wswitch u greške, a -Wno-error=switch čini da upozorenja -Wswitch ne budu greške, čak i kada je -Werror na snazi.

Napomena: Imajte na umu da navođenje
−Werror = foo automatski implicira −Wfoo. Međutim,
−Wno-error = foo ne podrazumeva ništa.


Ako želite da kompajler prekine kompilaciju pri prvoj grešci umesto da pokušava da nastavi i štampa dalje poruke o greškama možete koristiti opciju -Wfatal-errors.

Otklanjanje grešaka

Obično izvršna datoteka ne sadrži nikakve reference na originalni izvorni kod programa, kao što su imena promenljivih ili brojevi linija. Izvršna datoteka je jednostavno niz instrukcija mašinskog koda koje proizvodi kompajler. Ovo je nedovoljno za otklanjanje grešaka, pošto ne postoji jednostavan način da se pronađe uzrok greške ako dođe do pada programa.

Svaki iole veći program u jednom trenutku treba debagovati. Opcijom -g proizvode se informacije za otklanjanje grešaka u izvornom formatu operativnog sistema. One mogu biti korišćene za debagovanje od strane GDB-a (o njemu će više reči biti u poslednjem poglavlju kursa).

$ gcc  -g  fajl.c
Na sličan način možete koristiti i neke od sledećih opcije:

komandna opcija opis komandne opcije
-ggdb Proizvodi informacije za otklanjenje grašaka specijalno za GDB.
-Q Omogućava štampanje imena svake funkcije i statistika o svakom prolazu kada se završi.
-ftime-report Omogućava štampanje statistima o utrošenom vremenu pri svakom prolazu kada se završi.
-fmem-report Omogućava štampanje statistima o trajnoj alokaciji memorije pri svakom prolazu kada se završi.

Najbolje je da tokom razvoja programa opciju -g držiti stalno uključenom i isključite je tek pri generisanju verzije programa očišćene od grešaka.

Optimizacija

Kada završite sa debagovanjem programa možete uključiti opcije prevodioca namenjene optimizaciji. Uključivanjem opcija za optimizaciju kompajler pokušava da poboljša performanse i/ili veličinu koda nauštrb vremena kompilacije i eventualno mogućnosti otklanjanja grešaka u programu.

Možete koristiti neke od sledećih opcija:

opcija opis komande 1-vreme izvršavanja
2-veličina koda
3-količina memorije
4-vreme kompilacije
−O0 Smanjuje vreme kompilacije i obezbeđuje da otklanjanje grešaka daje očekivane rezultate. Ovo je podrazumevana opcija. 1 +
2 +
3 -
4 -
−O, −O1 Obezbeđuje optimizovano kompajliranje. Zahteva nešto više vremena i mnogo više memorije za složenije funkcije. 1 -
2 -
3 +
4 +
−O2 Obezbeđuje opsežniju optimizaciju. Preporučuje se za većinu kodova. U poređenju sa prethodnom opcija, ova opcija povećava i vreme kompilacije i performanse generisanog koda. 1 --
2
3 +
4 ++
−O3 Agresivnija je od -O2. Preporučuje se za kodove sa petljama koje uključuju intenzivne proračune sa pokretnim zarezom. 1 --
2
3 +
4 +++
−Os Minimizuje memoriju koju će izvršni kod koristiti. 1
2 --
3
4 ++
−Og Nudi razuman nivo optimizacije uz održavanje brze kompilacije i dobrog iskustva u otklanjanju grešaka. Bolji je izbor od -O0 za proizvodnju koda za otklanjanje grešaka jer su neki prolazi kompajlera koji prikupljaju informacije o otklanjanju grešaka onemogućeni sa -O0. 1
2
3
4
−Ofast Obezbeđuje optimizaciju slično kao i -O3 ali sa nekim dodacima. Dovodi do zanemarivanja stroge usklađenosti sa standardima. 1
2
3
4

Neke od opcija koje bivaju uključene sa -O1 su:

komandna opcija opis komandne opcije
-fdce Vrši eliminaciju mrtvog koda.
-fdse Vrši eliminaciju dodela promenljive koje u nastavku nisu korišćene.
-fmerge-constants Pokušava spajanje identičnih konstanti (konstante niza i konstante s pokretnim zarezom) u jedinicama kompilacije. Podrazumevana za optimizovanu kompilaciju ako je asembler i linker podržavaju. Koristite -fno-merge-constants da sprečite ovo ponašanje.
-fif-conversion Pokušava da transformiše uslovne skokove u ekvivalente bez grananja.
-fif-conversion2 Koristiti uslovno izvršavanje (gde je dostupno) da transformišete uslovne skokove u ekvivalente bez grananja.
-fdelayed-branch Ako je podržana za ciljnu mašinu, pokušava da promeni redosled instrukcija da bi se iskoristilo mesto za instrukcije koje je dostupna nakon odloženih instrukcija grananja.

Da biste saznali tačan skup optimizacija koji su omogućeni na svakom nivou, možete pozvati GCC pomoću:

$ gcc -K -help = optimizers