C/Używanie kompilatora
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.
#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 :
- COMPILER_PATH
- LIBRARY_PATH
- C_INCLUDE_PATH
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 :
- Strona domowa projektu GNU GCC
- Strona podręcznika systemu UNIX (man)
- stackoverflow questions tagged gcc
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]- C/Więcej o kompilowaniu: make/Makefile
- Kompilacja w systemie Linux
- Compiler explorer by Matt Godbolt
- pkg-config search path
- GNU C Compiler Internals w angielskiej wersji wikibooks
Źródła
[edytuj]- ↑ GCC (ang. GNU Compiler Collection)
- ↑ nadeausoftware : C/C++ tip: How to detect the compiler name and version using compiler predefined macros
- ↑ gcc.gnu.org onlinedocs : Common-Predefined-Macros.html
- ↑ CONTROLLING #INCLUDE IN C++ by BRIAN FITZGERALD
- ↑ stackoverflow question: what-are-the-gcc-default-include-directories
- ↑ Commands using gcc
- ↑ Dive into ELF files using readelf command by Himanshu Arora
- ↑ gcc gnu ver. 13.2.0: C-Dialect-Options
- ↑ stackoverflow question: what-is-the-default-c-std-standard-version-for-the-current-gcc-especially-on-u
- ↑ gentoo wiki : GCC optimization march
- ↑ stackoverflow question : which-loop-is-faster-in-c-while-loop-or-do-while-loop
- ↑ Opcje gcc
- ↑ developers redhat blog: address-and-thread-sanitizers-gcc
- ↑ gavinchou : gcc-address-sanitizer
- ↑ gnu online docs : gcc-11.3.0 Instrumentation-Options
- ↑ GCC and Make by Chua Hock-Chuan
- ↑ 3.19 Environment Variables Affecting GCC
- ↑ Dokumentacja Gcc: 3.13 Options for Linking
- ↑ stackoverflow question: usr-bin-ld-cannot-find-lstdc-for-ubuntu-while-trying-to-swift-build-perfe
- ↑ [ 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 ]
- ↑ gcc: error: stray ‘\342’ in program - www.giannistsakiris.com
- ↑ quora : What-does-stack-smashing-detected-terminated-mean-How-can-we-correct-it?