C/Używanie kompilatora

Z Wikibooks, biblioteki wolnych podręczników.
< C

Język C jest językiem kompilowanym, co oznacza, że potrzebuje specjalnego programu - kompilatora - który tłumaczy kod źródłowy, pisany przez człowieka, na język rozkazów danego komputera. W skrócie działanie kompilatora sprowadza się do czytania tekstowego pliku z kodem programu, raportowania ewentualnych błędów i produkowania pliku wynikowego.

Kompilatory[edytuj]

Kompilator uruchamiamy:

  • ze zintegrowanego środowiska programistycznego (ang. IDE)
  • z konsoli (linii poleceń)
  • online


Przejść do konsoli można dla systemów:

  • typu UNIX w trybie graficznym użyć programów gnome-terminal, konsole albo xterm,
  • Windows "Wiersz polecenia" (można go znaleźć w menu Akcesoria albo uruchomić wpisując w Start -> Uruchom... "cmd").


Lista kompilatorów

GCC[edytuj]

GCC (ang. GNU Compiler Collection)[1] jest to darmowy zestaw kompilatorów, m.in. języka C (gcc) rozwijany w ramach projektu GNU. Dostępny jest on na dużą ilość platform sprzętowych, obsługiwanych przez takie systemy operacyjne jak: AIX, *BSD, Linux, Mac OS X, SunOS, Windows. Na niektórych systemach (np. Windows) nie jest on jednak dostępny automatycznie. Należy zainstalować odpowiednie narzędzia (poprzedni rozdział).

Zmienne środowiska[edytuj]

W bashu:

 export CC="gcc" CFLAGS="-O3 -Wall"


W csh:

setenv CC "gcc"


Możesz dodać to polecenie do pliku ~/.bashrc, aby ustawić to ustawienie na stałe.

Wersja kompilatora[edytuj]

gcc --version

Otrzymujemy (przykładowy wynik):

gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
Copyright (C) 2013 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.


lub w c :[2] [3]

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
  printf("GCC_VERSION = %d.%d.%d \n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
  return 0;
}

Przykładowy wynik :

 GCC_VERSION = 4.8.4

Scieżki[edytuj]

Z pomocą komendy:[4]

echo "//" | gcc -xc++ -E -v -

przykładowy wynik :

 
Using built-in specs.
COLLECT_GCC=gcc
Target: x86_64-linux-gnu
Configured with: ../src/configure 
-v 
--with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' 
--with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs 
--enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ 
--prefix=/usr 
--program-suffix=-4.8 
--enable-shared 
--enable-linker-build-id 
--libexecdir=/usr/lib 
--without-included-gettext 
--enable-threads=posix 
--with-gxx-include-dir=/usr/include/c++/4.8 
--libdir=/usr/lib 
--enable-nls 
--with-sysroot=/ 
--enable-clocale=gnu 
--enable-libstdcxx-debug 
--enable-libstdcxx-time=yes 
--enable-gnu-unique-object 
--disable-libmudflap 
--enable-plugin 
--with-system-zlib 
--disable-browser-plugin 
--enable-java-awt=gtk 
--enable-gtk-cairo 
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre 
--enable-java-home 
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 
--with-arch-directory=amd64 
--with-ecj-jar=/usr/share/java/eclipse-ecj.jar 
--enable-objc-gc 
--enable-multiarch 
--disable-werror 
--with-arch-32=i686 
--with-abi=m64 
--with-multilib-list=m32,m64,mx32 
--with-tune=generic 
--enable-checking=release 
--build=x86_64-linux-gnu 
--host=x86_64-linux-gnu 
--target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) 
COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1plus 
 -E 
 -quiet 
 -v 
 -imultiarch x86_64-linux-gnu 
 -D_GNU_SOURCE - 
 -mtune=generic 
 -march=x86-64 
 -fstack-protector 
 -Wformat 
 -Wformat-security
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/4.8"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/4.8
 /usr/include/x86_64-linux-gnu/c++/4.8
 /usr/include/c++/4.8/backward
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "<stdin>"
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=x86-64'

Lista :


Z użyciem tylko gcc [5]

 gcc -E -Wp,-v -xc /dev/null
 
 
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/11/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
# 0 "/dev/null"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "/dev/null"

Symbole[edytuj]

Lista symboli compilatora :[6]

gcc -dM -E - < /dev/null

Plik wynikowy[edytuj]

Za pomocą komendy file sprawdzamy plik wynikowy:


file a.out

Przykładowy wynik:

a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x4f7368b40e4eeee54307e8491e0f2ace1405d841, not stripped

Możemy również użyć komendy: readlf[7]

biblioteki[edytuj]

Za pomocą komendy ldd sprawdzamy jakich bibliotek używa plik wynikowy:

ldd a.out

przykładowy wynik:

	linux-vdso.so.1 =>  (0x00007fff4ad68000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc5c7758000)
	libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007fc5c7549000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc5c732b000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc5c6f63000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fc5c7a7f000)

flagi[edytuj]

  • -L ( od ang Library) - pokazuje katalog gdzie są pliki binarne biblioteki
  • -E - powoduje wygenerowanie kodu programu ze zmianami, wprowadzonymi przez preprocesor
  • -S - zamiana kodu w języku C na kod asemblera (komenda: gcc -S plik.c spowoduje utworzenie pliku o nazwie plik.s, w którym znajdzie się kod asemblera)
  • -c - kompilacja bez łączenia z bibliotekami
  • -Ikatalog - ustawienie domyślnego katalogu z plikami nagłówkowymi na katalog, (duża litera i, od ang. Include)
  • -lbiblioteka - (mała litera l) : wymusza łączenie programu z podaną biblioteką = dołącza skompilowaną bibliotekę (np. -lGL)
  • -M = opcja preprocesora powodująca wypisanie ( dodanie do pliku Makefile) wymaganych opcji kompilacji. Jest używnaie przez gccmakedep program


Typowe zestawy flag

  • -Wall -Wextra -march=native -std=c99


std[edytuj]

Opcje sterujące dialektem C[8]

  • std
  • pedantic
  • ansi


Domyślny standard języka zależy od wersji kompilatora[9]

march[edytuj]

Mikroarchitektura procesora ( march )

Sprawdzamy za pomocą cat lub gcc : [10]

  gcc -c -Q -march=native --help=target

przykładowy wynik :

The following options are target specific:
  -m128bit-long-double        		[disabled]
  -m16                        		[disabled]
  -m32                        		[disabled]
  -m3dnow                     		[disabled]
  -m3dnowa                    		[disabled]
  -m64                        		[enabled]
  -m80387                     		[enabled]
  -m8bit-idiv                 		[disabled]
  -m96bit-long-double         		[enabled]
  -mabi=                      		sysv
  -mabm                       		[enabled]
  -maccumulate-outgoing-args  		[disabled]
  -maddress-mode=             		short
  -madx                       		[disabled]
  -maes                       		[enabled]
  -malign-data=               		compat
  -malign-double              		[disabled]
  -malign-functions=          		0
  -malign-jumps=              		0
  -malign-loops=              		0
  -malign-stringops           		[enabled]
  -mandroid                   		[disabled]
  -march=                     		haswell
  -masm=                      		att
  -mavx                       		[enabled]
  -mavx2                      		[enabled]
  -mavx256-split-unaligned-load 	[disabled]
  -mavx256-split-unaligned-store 	[disabled]
  -mavx512bw                  		[disabled]
  -mavx512cd                  		[disabled]
  -mavx512dq                  		[disabled]
  -mavx512er                  		[disabled]
  -mavx512f                   		[disabled]
  -mavx512ifma                		[disabled]
  -mavx512pf                  		[disabled]
  -mavx512vbmi                		[disabled]
  -mavx512vl                  		[disabled]
  -mbionic                    		[disabled]
  -mbmi                       		[enabled]
  -mbmi2                      		[enabled]
  -mbranch-cost=              		0
  -mcld                       		[disabled]
  -mclflushopt                		[disabled]
  -mclwb                      		[disabled]
  -mcmodel=                   		32
  -mcpu=                      		
  -mcrc32                     		[disabled]
  -mcx16                      		[enabled]
  -mdispatch-scheduler        		[disabled]
  -mdump-tune-features        		[disabled]
  -mf16c                      		[enabled]
  -mfancy-math-387            		[enabled]
  -mfentry                    		[enabled]
  -mfma                       		[enabled]
  -mfma4                      		[disabled]
  -mforce-drap                		[disabled]
  -mfp-ret-in-387             		[enabled]
  -mfpmath=                   		387
  -mfsgsbase                  		[enabled]
  -mfused-madd                		
  -mfxsr                      		[enabled]
  -mglibc                     		[enabled]
  -mhard-float                		[enabled]
  -mhle                       		[disabled]
  -mieee-fp                   		[enabled]
  -mincoming-stack-boundary=  		0
  -minline-all-stringops      		[disabled]
  -minline-stringops-dynamically 	[disabled]
  -mintel-syntax              		
  -mlarge-data-threshold=     		0x10000
  -mlong-double-128           		[disabled]
  -mlong-double-64            		[disabled]
  -mlong-double-80            		[enabled]
  -mlwp                       		[disabled]
  -mlzcnt                     		[enabled]
  -mmemcpy-strategy=          		
  -mmemset-strategy=          		
  -mmmx                       		[enabled]
  -mmovbe                     		[enabled]
  -mmpx                       		[disabled]
  -mms-bitfields              		[disabled]
  -mmwaitx                    		[disabled]
  -mno-align-stringops        		[disabled]
  -mno-default                		[disabled]
  -mno-fancy-math-387         		[disabled]
  -mno-push-args              		[disabled]
  -mno-red-zone               		[disabled]
  -mno-sse4                   		[disabled]
  -mnop-mcount                		[disabled]
  -momit-leaf-frame-pointer   		[disabled]
  -mpc32                      		[disabled]
  -mpc64                      		[disabled]
  -mpc80                      		[disabled]
  -mpclmul                    		[enabled]
  -mpcommit                   		[disabled]
  -mpopcnt                    		[enabled]
  -mprefer-avx128             		[disabled]
  -mpreferred-stack-boundary= 		0
  -mprefetchwt1               		[disabled]
  -mprfchw                    		[disabled]
  -mpush-args                 		[enabled]
  -mrdrnd                     		[enabled]
  -mrdseed                    		[disabled]
  -mrecip                     		[disabled]
  -mrecip=                    		
  -mrecord-mcount             		[disabled]
  -mred-zone                  		[enabled]
  -mregparm=                  		0
  -mrtd                       		[disabled]
  -mrtm                       		[disabled]
  -msahf                      		[enabled]
  -msha                       		[disabled]
  -mskip-rax-setup            		[disabled]
  -msoft-float                		[disabled]
  -msse                       		[enabled]
  -msse2                      		[enabled]
  -msse2avx                   		[disabled]
  -msse3                      		[enabled]
  -msse4                      		[enabled]
  -msse4.1                    		[enabled]
  -msse4.2                    		[enabled]
  -msse4a                     		[disabled]
  -msse5                      		
  -msseregparm                		[disabled]
  -mssse3                     		[enabled]
  -mstack-arg-probe           		[disabled]
  -mstack-protector-guard=    		tls
  -mstackrealign              		[enabled]
  -mstringop-strategy=        		[default]
  -mtbm                       		[disabled]
  -mtls-dialect=              		gnu
  -mtls-direct-seg-refs       		[enabled]
  -mtune-ctrl=                		
  -mtune=                     		haswell
  -muclibc                    		[disabled]
  -mveclibabi=                		[default]
  -mvect8-ret-in-mem          		[disabled]
  -mvzeroupper                		[disabled]
  -mx32                       		[disabled]
  -mxop                       		[disabled]
  -mxsave                     		[enabled]
  -mxsavec                    		[disabled]
  -mxsaveopt                  		[enabled]
  -mxsaves                    		[disabled]

  Known assembler dialects (for use with the -masm-dialect= option):
    att intel

  Known ABIs (for use with the -mabi= option):
    ms sysv

  Known code models (for use with the -mcmodel= option):
    32 kernel large medium small

  Valid arguments to -mfpmath=:
    387 387+sse 387,sse both sse sse+387 sse,387

  Known data alignment choices (for use with the -malign-data= option):
    abi cacheline compat

  Known vectorization library ABIs (for use with the -mveclibabi= option):
    acml svml

  Known address mode (for use with the -maddress-mode= option):
    long short

  Known stack protector guard (for use with the -mstack-protector-guard= option):
    global tls

  Valid arguments to -mstringop-strategy=:
    byte_loop libcall loop rep_4byte rep_8byte rep_byte unrolled_loop
    vector_loop

  Known TLS dialects (for use with the -mtls-dialect= option):
    gnu gnu2

Używamy :

 -march=native

lub tutaj

 -march=haswell

S[edytuj]

Plik :[11]

int main() {


  int a = 0;


  while (a < 100) {
    a++;
  }


  a = 0;
  do {
    a++;
  }while(a < 100);


  for ( a=0; a < 100; ++a){ 
    a++;}


  return 0;
}

Skompilujemy :


 gcc -S l.c -Wall

Oprócz pliku a.out otrzymamy dodatkowy plik z rozszerzeniem "s":

a.out  l.c  l.s

który zawiera kodem assemblera :

	.file	"l.c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$0, -4(%rbp)
	jmp	.L2
.L3:
	addl	$1, -4(%rbp)
.L2:
	cmpl	$99, -4(%rbp)
	jle	.L3
	movl	$0, -4(%rbp)
.L4:
	addl	$1, -4(%rbp)
	cmpl	$99, -4(%rbp)
	jle	.L4
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 5.4.1-2ubuntu1~16.04) 5.4.1 20160904"
	.section	.note.GNU-stack,"",@progbits

v ( ustawienia)[edytuj]

Użycie flagi v powoduje wydrukowanie na standardowym wyjściu błędu (ang. standard error output) komend uruchamianych w trakcie kompilacji oraz wersji programu kompilatora [12]

gcc -v

przykładowy wynik:

 Using built-in specs.
 COLLECT_GCC=gcc
 COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
 Target: x86_64-linux-gnu
 Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.8.1-10ubuntu9' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9)

wykrywacze błędów pamięci i wątków[edytuj]

Od wersji 4.8 kompilatory C i C++ z GNU Compiler Collection są wyposażone we wbudowane wykrywacze błędów pamięci i wątków ( ang. Address and Thread Sanitizers) [13][14]

Rodzaje nieprawidłowych dostępów do pamięci, które można dziś wykryć, to:

  • Dostęp poza zakresem dla obiektów lokalnych, globalnych i sterty
  • Dostępy typu „use-after-free” dla obiektów sterty

Opcje instrumentacji programu ( ang. Program Instrumentation Options ) [15]

  • -fsanitize=style -fsanitize-recover -fsanitize-recover=style
  • -fasan-shadow-offset=number -fsanitize-sections=s1,s2,...
  • -fsanitize-undefined-trap-on-error -fbounds-check

Pomoc[edytuj]

Offline :

man gcc

lub w postaci pliku tekstowego:[16]

man gcc | col -b > gcc.txt

lub info:

info gcc


Online :

Program gccmakedep tworzy zależności w plikach makefile za pomocą

gcc -M
gccmakedep

Kompilacja[edytuj]

Aby skompilować kod języka C za pomocą kompilatora G++, napisany wcześniej w dowolnym edytorze tekstu, należy uruchomić program z odpowiednimi parametrami. Podstawowym parametrem, który jest wymagany, jest nazwa pliku zawierającego kod programu który chcemy skompilować.

gcc kod.c
Rezultatem kompilacji będzie plik wykonywalny, z domyślną nazwą (w systemach Unix jest to "a.out").

Jest to metoda niezalecana, ponieważ w przypadku, gdy skompilujemy w jednym katalogu kilka plików z kodem, kolejne pliki wykonywalne zostaną nadpisane i w rezultacie otrzymamy tylko jeden (ostatni) skompilowany kod. Aby wymusić na G++ nazwę pliku wykonywalnego musimy skorzystać z parametru "-o <nazwa>":

gcc -o program kod.c
W rezultacie otrzymujemy plik wykonywalny o nazwie program.

Pracując nad złożonym programem składającym się z kilku plików źródłowych (.c), możemy skompilować je niezależnie od siebie, tworząc tak zwane pliki typu obiekt, z rozszerzeniem .o (ang. Object File). Następnie możemy stworzyć z nich jednolity program w procesie konsolidacji (linkowaniu). Jest to bardzo wygodne i praktyczne rozwiązanie ze względu na to, iż nie jesteśmy zmuszeni kompilować wszystkich plików tworzących program za każdym razem na nowo, a jedynie te, w których wprowadziliśmy zmiany Aby skompilować plik bez linkowania używamy parametru "-c <plik>":

gcc -o program1.o -c kod1.c
gcc -o program2.o -c kod2.c

Otrzymujemy w ten sposób pliki typu obiekt program1.o i program2.o. A następnie tworzymy z nich program główny:

gcc -o program program1.o program2.o

Możemy użyć również flag, m.in. aby włączyć dokładne, rygorystyczne sprawdzanie napisanego kodu (co może być przydatne, jeśli chcemy dążyć do perfekcji), używamy przełączników:

gcc kod.c -o program -Werror -Wall -W -pedantic -ansi

Borland[edytuj]

Zobacz podręcznik Borland C++ Compiler.

Błędy kompilacji[edytuj]

Jedną z najbardziej podstawowych umiejętności, które musi posiąść początkujący programista jest umiejętność rozumienia komunikatów o różnego rodzaju błędach, które sygnalizuje kompilator. Wszystkie te informacje pomogą Ci szybko wychwycić ewentualne błędy (których na początku zawsze jest bardzo dużo). Nie martw się, że na początku dość często będziesz oglądał wydruki błędów, zasygnalizowanych przez kompilator - nawet zaawansowanym programistom się to zdarza. Kompilator ma za zadanie pomóc Ci w szybkiej poprawie ewentualnych błędów, dlatego też umiejętność analizy komunikatów o błędach jest tak ważna.

Zaczynamy analizę od pierwszego komunikatu kompilatora. Poprawiamy błąd i ponownie kompilujemy (może wtedy znikną pozostałe błędy).

GCC[edytuj]

Komunikaty[edytuj]

Język komunikatów zależy od zmiennych środowiska, np.:[17]

  • LANG
  • LC_CTYPE
  • LC_MESSAGES
  • LC_ALL


echo $LANG
pl_PL.UTF-8

Błędy składniowe[edytuj]

Kompilator jest w stanie wychwycić błędy składniowe, które z pewnością będziesz popełniał. Kompilator GCC wyświetla je w następującej formie:

 nazwa_pliku.c:numer_linijki:opis błędu

Kompilator dość często podaje także nazwę funkcji, w której wystąpił błąd.


Przykładowo, błąd deklaracji zmiennej w pliku test.c:

#include <stdio.h>

int main ()
{
 intr r;
 printf ("%d\n", r);
}

Spowoduje wygenerowanie następującego komunikatu o błędzie:

test.c: In function ‘main’:
test.c:5: error: ‘intr’ undeclared (first use in this function)
test.c:5: error: (Each undeclared identifier is reported only once
test.c:5: error: for each function it appears in.)
test.c:5: error: syntax error before ‘r’
test.c:6: error: ‘r’ undeclared (first use in this function)

Co widzimy w raporcie o błędach?

W linii 5 użyliśmy nieznanego (undeclared) identyfikatora intr - kompilator mówi, że nie zna tego identyfikatora, jest to pierwsze użycie w danej funkcji i że więcej nie ostrzeże o użyciu tego identyfikatora w tej funkcji. Ponieważ intr nie został rozpoznany jako żaden znany typ, linijka intr r; nie została rozpoznana jako deklaracja zmiennej i kompilator zgłasza błąd składniowy (syntax error). W konsekwencji r nie zostało rozpoznane jako zmienna i kompilator zgłosi to jeszcze w następnej linijce, gdzie używamy r.


error: initializer element is not constant

Ten błąd powstaje gdy:

  • za pomocą jednej instrukcji deklarujemy i inicjujemy zmienną
  • do nadania wartości używamy wyrażenia a nie za stałej wartości (liczba)

Rozwiązaniem jest rozdzielenie deklaracji i inicjalizacji na 2 instrukcje.

Ostrzeżenie: niejawna deklaracja funkcji, np.:

t.c:696:17: warning: implicit declaration of function ‘dDrawLine’

powstanie gdy:

  • nie dołączymy odpowiedniej biblioteki zawierającej deklarację funkcji,
  • deklaracja własnej funkcji będzie zawarta w programie ale nie zostanie rozpoznana z powodu błędów składniowych


Inny błąd :

membership_new.c:63:9: error: expected ‘,’ or ‘;’ before ‘int’

przyczyna: w linii poprzedzającej linię 63 brak na końcu średnika (;) lub przecinka (,)

Błędy związane z bibliotekami[edytuj]

linker[edytuj]

Przykładowy komunikat:

/usr/bin/ld: cannot find -lXmu

Problem jest związany z opcją oznaczoną literą l linkera (ld):[18]

-llibrary

Linker nie może znaleźć biblioteki liblibrary, czyli w tym przypadku libXmu.

Sprawdzamy czy mamy taką biblioteką zainstalowaną, jeśli nie to szukamy pakietu libXmu np. w menadżerze pakietów Synaptic (w Ubuntu libXmu-dev) i instalujemy go.


Nowy błąd ( pojawił się po zainstalowanie clang)

/usr/bin/ld: cannot find -lstdc++: No such file or directory

Oznacza że link symboliczny ( ang. symbolic link) libstdc++.so wskazuje na nieistniejacy plik[19]

cd /usr/lib; ls

Możliwości

  • nie ma pliku libstdc++.so w katalogu /usr/lib/
  • są 2 pliki libstdc++.so
sudo apt-get update && sudo apt-get upgrade

Znajdujemy plik biblioteki libstdc++.so.6

sudo find / -name libstdc++.so.6

i tworzymy plik:

sudo ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/libstdc++.so

undefined references[edytuj]

Komunikat "undefined references" pochodzi głównie z linkera.

Przykładowy komunikat dotyczący biblioteki matematycznej: [20]

undefined reference to 'pow' collect2: error: ld returned 1 exit status

Może być spowodowany kolejnością linkowania bibliotek, np w pliku MAKFILE, dobra kolejność:

LIBS =  -lcairo -lmpfr -lm 

zła:

LIBS =  -lm -lcairo -lmpfr


Komunikat :

  undefined reference to symbol 'pow@@GLIBC_2.2.5'
  • przyczyna: ( użycie funkcji pow z biblioteki math
  • rozwiązanie : dodać -lm do opcji kompilacji

stray[edytuj]

r1.c:194:3: error: stray ‘\342’ in program
r1.c:194:3: error: stray ‘\210’ in program
r1.c:194:3: error: stray ‘\222’ in program

Błąd ten jest spowodowany występowaniem w kodzie innych znaków niż ASCI[21]. Prawdopodobnie skopiowano znaki z innego programu, np.:

  • pliku pdf
  • pliku/programu Microsoft Word
  • kalkulatora gcalctool

Rozwiązanie:

  • usuń skopiowany tekst
  • wpisz go ręcznie

*** stack smashing detected ***: terminated[edytuj]

  • You have a buffer overflow! [22]

Czy można określić lub ustawić opcje kompilatora z poziomu kodu źródłowego w gcc?[edytuj]

Nie. Zamiast tego umieszczasz w źródle kod specyficzny dla kompilatora/platformy/systemu operacyjnego i otaczasz go odpowiednimi instrukcjami ifdef.

  
#ifdef __GNUC__
/*code for GNU C compiler */
#elif _MSC_VER
/*usually has the version number in _MSC_VER*/
/*code specific to MSVC compiler*/
#elif __BORLANDC__
/*code specific to borland compilers*/
#elif __MINGW32__
/*code specific to mingw compilers*/
#endif

Czy można wykryć flagi kompilacji GCC z pliku binarnego?[edytuj]

GCC ma tę funkcję w wersji 4.3, jeśli zostanie o to poproszony podczas kompilacji kodu: Nowy przełącznik wiersza poleceń

-frecord-gcc-switches 

powoduje, że wiersz poleceń użyty do wywołania kompilatora zostanie zapisany w pliku obiektowym to się tworzy. Dokładny format tego nagrania zależy od formatu docelowego i pliku binarnego, ale zwykle ma formę sekcji notatki zawierającej tekst ASCII.

Zobacz również[edytuj]

Źródła[edytuj]

  1. GCC (ang. GNU Compiler Collection)
  2. nadeausoftware : C/C++ tip: How to detect the compiler name and version using compiler predefined macros
  3. gcc.gnu.org onlinedocs : Common-Predefined-Macros.html
  4. CONTROLLING #INCLUDE IN C++ by BRIAN FITZGERALD
  5. stackoverflow question: what-are-the-gcc-default-include-directories
  6. Commands using gcc
  7. Dive into ELF files using readelf command by Himanshu Arora
  8. gcc gnu ver. 13.2.0: C-Dialect-Options
  9. stackoverflow question: what-is-the-default-c-std-standard-version-for-the-current-gcc-especially-on-u
  10. gentoo wiki : GCC optimization march
  11. stackoverflow question : which-loop-is-faster-in-c-while-loop-or-do-while-loop
  12. Opcje gcc
  13. developers redhat blog: address-and-thread-sanitizers-gcc
  14. gavinchou : gcc-address-sanitizer
  15. gnu online docs : gcc-11.3.0 Instrumentation-Options
  16. GCC and Make by Chua Hock-Chuan
  17. 3.19 Environment Variables Affecting GCC
  18. Dokumentacja Gcc: 3.13 Options for Linking
  19. stackoverflow question: usr-bin-ld-cannot-find-lstdc-for-ubuntu-while-trying-to-swift-build-perfe
  20. [ http://stackoverflow.com/questions/12824134/undefined-reference-to-pow-in-c-despite-including-math-h Undefined reference to pow( ) in C, despite including math.h ]
  21. gcc: error: stray ‘\342’ in program - www.giannistsakiris.com
  22. quora : What-does-stack-smashing-detected-terminated-mean-How-can-we-correct-it?