Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!

Ogłoszenie

Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.

#1  2013-03-31 21:44:53

  Onegda - Nowy użytkownik

Onegda
Nowy użytkownik
Zarejestrowany: 2013-03-31

Kompilator gcc a funkcja log();

Witam serdecznie.

Przyznam szczerze, że przejrzałam forum pod kątem problemu z linkerem, ale nie udało mi się znaleźć satysfakcjonującej odpowiedzi. Usiłuję napisać prosty programik używający wątki w języku C (mam policzyć entropię w bitach). Wszystko szło dobrze, dopóki nie chciałam użyć funkcji log(). Kiedy jest ona w zewnętrznej funkcji kompilator wyrzuca mi błąd "undefined reference to 'log'". Znalazłam w jednym z tematów, że "wystarczy" dołączyć bibliotekę math.h. Była dołączona od samego początku. Dodatkowo ściągnęłam i zainstalowałam repo z bibliotekami do gcc na wszelki wypadek i dalej był problem. Zmiana na funkcję log10(); też niewiele pomogła (mogę sobie pozwolić na taką podmiankę, ponieważ chcę policzyć logarytm przy podstawie 2, więc z praw działania na logarytmach wystarczy, że zastosuję iloraz). W każdym razie zmienną do logarytmu wprowadzam poprzez argument zewnętrznej funkcji. (Zewnętrznej, czyli mam namyśli funkcję, którą stworzyłam sobie sama, a nie funkcję główną main()). Dopatrzyłam się, że właśnie tutaj jest błąd.

Niemniej, jeśli umieszczę funkcję log() (lub log10()) w mainie, podam argument liczbowo (np. log10(10)), to wylicza wartość z błędem, lecz kompiluje bez błędu.

Czy ktoś z Was wie, na czym może polegać problem? Domyślam się, że prawdopodobnie to będzie "bardzo łatwe, bardzo naiwne i wstyd, że nie wiem", niemniej walczę z tym już dobrą godzinę : )


____________
Zapomniałam napisać: kompiluję na Debianie. Natomiast na Ubuntu (zupełnie inny komputer, dodam dla porządku), rzecz wygląda tak samo.

______________
Właściwie to rozwiązane, więc albo można usunąć (przepraszam moderatorze za kłopot (: ), albo podam rozwiązanie, że tak zażartuję, dla potomnych. Mianowicie przy kompilacji nie podałam -lm.
Dziękuję i wybaczcie za zawracanie głowy.

Ostatnio edytowany przez Onegda (2013-03-31 22:40:13)

Offline

 

#2  2013-04-01 00:07:08

  gindek - Zubr, bydle na etacie.

gindek
Zubr, bydle na etacie.
Skąd: Z puszczy.
Zarejestrowany: 2008-12-08

Re: Kompilator gcc a funkcja log();

no ok, ale gdzie są źródła ?


" Wojny przychodzą i odchodzą, a moi żołnierze są wieczni"


"Zbuduj mały, dziarski router z udostępnionych przez prowadzącego części od Kamaza?"

Offline

 

#3  2013-04-01 11:41:53

  HAL9000 - Użytkownik

HAL9000
Użytkownik
Zarejestrowany: 2006-04-22

Re: Kompilator gcc a funkcja log();

http://www.network-theory.co.uk/docs/gccintro/gccintro_17.html

2.7 Linkowanie z bibliotekami zewnętrznymi
Biblioteka jest kolekcją skompilowanych plików obiektowych, które mogą być dołączone do programu. Najbardziej powszechne zastosowanie bibliotek to dostarczenie funkcji systemowych, takich jak pierwiastek kwadratowy ( sqrt ) z biblioteki matematycznej w C.
Biblioteki są zazwyczaj przechowywane w specjalnych plikach archiwów z rozszerzeniem '.a' określanych jako biblioteki statyczne. Są one tworzone z plików obiektowych przy użyciu oddzielnego narzędzia GNU archiwizator ar i używane przez linker do znalezienia/rozwiązania referencji do funkcji w czasie kompilacji. (bardziej podczas linkowania) ...
Standardowe biblioteki systemowe są zazwyczaj umieszczone w katalogach '/usr/lib' i '/lib'. Przykładowo biblioteka matematyczna C jest zazwyczaj przechowywana w pliku '/usr/lib/libm.a' w systemach uniksowych. Odpowiednie deklaracje dla funkcji z tej biblioteki są umieszczone w pliku nagłówkowym '/usr/include/math.h'. Standardowa biblioteka C jest zapisana w '/usr/lib/libc.a' i zawiera funkcje standardu ANSI/ISO C takie jak printf, ta biblioteka jest linkowana domyślnie do każdego programu napisanego w C (podczas linkowania).
Oto przykład programu, który wywołuje zewnętrzną funkcje sqrt z biblioteki matematycznej 'libm.a'

Kod:

#include <math.h>
#include <stdio.h>
int
main (void)
{
  double x = sqrt (2.0);
  printf ("Pierwiastek kwadratowy z 2.0 wynosi %f\n", x);
  return 0;
}

Próba stworzenia pliku wykonywalnego z tego kodu powoduje wygenerowanie błędu przez kompilator w czasie linkowania.

Kod:

$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function `main':
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference 
  to `sqrt'

Problem polega na tym, iż nie można znaleźć referencji do funkcji sqrt bez zewnętrznej biblioteki matematycznej 'libm.a'. Funkcja sqrt nie jest zdefiniowana w programie lub w domyślnej bibliotece 'libc.a' a kompilator nie linkuje pliku 'libm.a' chyba że w sposób jasny tego zażądamy. Plik wspomniany w komunikacie o błędzie ‘/tmp/ccbR60jm.o’ jest tymczasowym plikiem obiektowym stworzonym przez kompilator z calc.c aby kontynuować proces linkowania.
Aby umożliwić kompilatorowi linkowanie funkcji sqrt do naszego programu musimy dostarczyć odpowiednią bibliotekę w tym przypadku 'libm.a'. Jeden oczywisty ale niewygodny sposób aby to zrobić to podać nazwę pliku w linii poleceń:

Kod:

$ gcc -Wall calc.c /usr/lib/libm.a -o calc

Biblioteka 'libm.a' zawiera definicje wszystkich funkcji matematycznych takich jak sin, cos, exp, log, sqrt. Linker przeszukuje tą biblioteke w poszukiwaniu pliku obiektowego zawierającego funkcje sqrt.
Kiedy plik obiektowy funkcji sqrt zostanie znaleziony nasz program może być linkowany i program wykonywalny może powstać.

Kod:

$ ./calc 
The square root of 2.0 is 1.414214

Plik wykonywalny zawiera kod maszynowy dla funkcji main i kod maszynowy dla funkcji sqrt skopiowany z pliku obiektowego w bibliotece 'libm.a'.
Aby uniknąć długich ścieżek z linii poleceń kompilator ma opcję '-l' aby linkować z zewnętrznymi bibliotekami. Przykładowo:

Kod:

$ gcc -Wall calc.c -lm -o calc

jest równoważne z podaniem pełnej ścieżki do biblioteki.
Ogólnie opcja -lNAZWA spróbuje linkować z plikiem obiektowym z pliku biblioteki 'libNAZWA.a' w standardowym katalogu bibliotek. ...

Gdyby ktoś nic z tego nie zrozumiał to ma to wygladac tak:
1) kompilujemy i tylko kompilujemy wiec opcje dla linkera na tym etapie nie sa potrzebne
gcc -o prog.o -c prog.c
2) linkujemy wiec dodajemy opcje dla linkera:
gcc -lm -o prog prog.o
Jezeli komus bedzie sie chcialo prosz sprawdzic gdyz ja w tej chwili uzywam windowsa nie moge tego zweryfikowac

Lektura dodatkowa:
http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html


For some reason I'm thinking I'm still 25 but I act like I'm 12.

Offline

 

Stopka forum

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson
To nie jest tylko forum, to nasza mała ojczyzna ;-)