Sziasztok!
gcc-vel első lépéseim tenném meg, linux alatt.
Van egy main.c, amiben szerepel az alábbi pár sor a fájl elején:
#include "stdio.h"
#include "SAJAT_header.h"
#include "SAJAT_header2.h"
Van a main.c mellett egy könyvtár, aminek a neve sajINC, ebben van a fent említett két fájl.
A fordítást az alábbi paranccsal kívánom megtenni (egyelore az a.out bináris tökéletesen meg fog felelni):
gcc -I sajINC/ main.c
A problémám, hogy
root@beagleboard:/usr/local/src/SAJAT# gcc -I sajINC main.c
/tmp/ccuUV9Lv.o: In function `main':
main.c:(.text+0x4): undefined reference to `EGV'
main.c:(.text+0x8): undefined reference to `EGV'
holott a SAJAT_header.h tartalmazza az alábbi sort:
extern int EGV;
Úgy tűnik, mintha mégsem include-olná a headert. Mi a bánat miatt?
- 3119 megtekintés
Hozzászólások
amikor a gcc paracsot kiadod, ket lepes tortenik:
- forditas
- linkeles.
A forditas hiba nelkul tortent, a linkeles hasalt el.
Tehat a program a C nyelv szerint jo, amde megse mukodokepes.
Az a baj, hogy az
'extern EGV'
azt jelenti, hogy: "valami masik modulban van egy EGV valtozo, ezt most a C nyelvnek elmondom, hogy a C fordito majd tudjon mit kezdeni vele, ha talalkozik az EGV valtozoval. Es kesobb a linker majd megtalalja az EGV valtozot."
viszont nem csinaltal masik modult, amiben ott is lenne ez az EGV valtozo. Igy a linker nem talalja meg.
2 lehetseges megoldas:
- amig nem tudod, hogy mi az a ket modul, addig nem hasznalod az extern kulcsszot
- csinalsz egy masik modult az alabbi egyetlen sorral:
int EGV;
es azt is leforditod, es a ket modult osszelinkeled.
- A hozzászóláshoz be kell jelentkezni
"2 lehetseges megoldas:"
3. lehetoseg: -c-vel hivja meg, igy nem lesz linkeles. Irta, hogy egyelore a .o eleg.
Szerk: jah lehet, hogy rosszul ertelmeztem, nem .o kell neki...
----------------------
"ONE OF THESE DAYS I'M GOING TO CUT YOU INTO LITTLE PIECES!!!$E$%#$#%^*^"
--> YouTube csatornám
- A hozzászóláshoz be kell jelentkezni
Csak picit off:
> amikor a gcc paracsot kiadod, ket lepes tortenik:
>
> - forditas
> - linkeles.
Érdekes a megközelítésed, mivel feljebb aztán azt írod, hogy az include-olással lehet "szimulálni" a modulokat c-ben. Szerintem pont emiatt inkább három lépést szokás említeni: preprocessing, compiling, linking.
Tudom, hogy - szinte - bármeddig bonthatóak, részletezhetőek ezek a lépések, mégis az előfeldolgozás jól elkülöníthető része a fordítási folyamatnak.
- A hozzászóláshoz be kell jelentkezni
Bizonyos nyelvekben a nyelvi modulhivatkozas kozvetlenul hozza van rendelve a linkelesi kornyezet osszerakasahoz.
A C nem ilyen. A C-ben egyaltalan nincsen nyelvi tamogatas a modul fogalmahoz, csak "olyan mintha" dolgok vannak.
Ha egy modul programjat (implementaciojat) berakod egy foo.c -be, es
ugyanennek a modulnak a definiciojat berakod egy foo.h -ba, akkor az
#include "foo.h"
es a forditas utan a foo.o -val valo osszelinkelessel egeszen jol lehet utanozni azt, amit mas nyelvek modulnak hivnak.
Viszint itt a C -nek, maganak a nyelvnek nem resze sem az #include, sem a linker. Es nincsen semmi-semmi segitseg, hogy a foo.h tenyleg a foo.c -ben implementalt kod definiciojat/prototipusat tartalmazza. Vagy valmi tok mast.
Azt hiszem, a jo C programozashoz szukseg van alapveto assembler es alapveto oprendszer felepules ismeretre. Azonban sok C programozoval talalkoztam, akinek egyaltalan, semmi ismerete nem volt ezekrol.
- A hozzászóláshoz be kell jelentkezni
Azt gondolom, hogy (ha jól halbiologizálom ki) ez a feltétel teljesül (bár ezzel kapcsolatban a post-om hiányos), hiszen van egy sajat_header.c fájl is, ahol szerepel egy ilyen sor:
int EGV;
Akkor eszerint, ha jól értem, a fordításkori parancs nem jó, hanem valahogy úgy kellene fordítanom, hogy ebből a két fájlból (sajat_header.h és sajat_header.c) készüljön egy sajat_header.o, majd a main.c-t úgy kell fordítanom, hogy a linker használja fel a sajat_header.o fájlt?
- A hozzászóláshoz be kell jelentkezni
igen. Mondjuk:
cc -o programom main.c sajat_header.c
Aztan ha keloen nagyok lesznek es nem akarsz mindig mindent forditani, akkor johet a make es a Makefile, amivel automatizalni lehet a dolgokat.
- A hozzászóláshoz be kell jelentkezni
Ilyennel is próbálkoztam, mi lehet a hiba benne?
Egy mappába raktam mindent, és
gcc `ls |grep "\.c$"`
De itt meg bármit használtam, ami a headerekben volt, "fagyasztotta" a lefordítás után elindított bináris processzét.
- A hozzászóláshoz be kell jelentkezni
Nem oly nehéz a google-n rákeresni, hogy gcc multiple source file tutorial, és még használható találatokat is kapsz.
Például: http://www.network-theory.co.uk/docs/gccintro/gccintro_11.html
http://crasseux.com/books/ctutorial/Compiling-multiple-files.html
Érdemes megérteni, hogy mi történik, mi az object, mi a header, mire jó az extern, mi a header guard stb.
- A hozzászóláshoz be kell jelentkezni
Itt ezeken a linkeken azt olvastuk, hogy az alábbi szerkezet lefordításához
main.c:
#include "nyenyere.h"
int main(void)
{
EGV = 5;
ASD();
return 0;
}
és nyenyere.c:
#include "nyenyere.h"
int EGV;
void ASD(void)
{
int temp;
temp += EGV;
}
és nyenyere.h:
#ifndef _NYENYERE_H_
#define _NYENYERE_H_
extern int EGV;
void ASD(void);
#endif
az alábbi parancsot kell alkalmaznom:
gcc main.c -o newhello
Ehhez képest nekem ezt mondja a linker (?):
root@beagleboard:/usr/local/src/nyenyere# gcc main.c -o newhello
/tmp/ccdS58n9.o: In function `main':
main.c:(.text+0x4): undefined reference to `EGV'
main.c:(.text+0x8): undefined reference to `EGV'
main.c:(.text+0x12): undefined reference to `ASD'
collect2: ld returned 1 exit status
Ennek a link szerint le kell fordulnia, mert a main.c include-olja a nyenyere.h-t, amihez viszont a nyenyere.c tartozik. A nyenyere.h-ban deklarált és a nyenyere.c-ben definiált részek formája, neve, típusa, stb. megegyezik, így ezek együtt egy modult alkotnak.
Nekem viszont nem fordul.
És akkor miért is?
- A hozzászóláshoz be kell jelentkezni
Én nem ezt olvastam.
- A hozzászóláshoz be kell jelentkezni
1. lefordul. Ezt ugy hivjuk, hogy lefordul. A linkelesnel esik el: nem linkelodik.
2. ez hibas. A nyenyere.c -ben ilyen esetben ne include-oljad be a nyenyere.h -t. Mert akkor a fordito a kovetkezovel talalkozik:
extern int EGV;
int EGV;
3. Koncepcionalisan is hibas az extern hasznalata ugy alatalaban, hasonloan, mint a goto hasznalata. Tessek a kovetkezot hasznalni:
nyenyere.h:
#ifndef _NYENYERE_H_
#define _NYENYERE_H_
int get_EGV(void);
int inc_EGV(void);
#endif
nyenyere.c:
#include "nyenyere.h"
static int EGV=0;
int get_EGV()
{
return EGV;
}
void inc_EGV()
{
++EGV;
}
- A hozzászóláshoz be kell jelentkezni
A források ismerete nélkül semmit nem lehet mondani arról, hogy mi "fagyasztotta".
Mindenesetre ha minden ami az adott alkalmazáshoz szükséges - és csak az - ugyanabban a könyvtárban van, akkor a
gcc *.c
pontosan a fentihez hasonló módon fog futni, de legalább áttekinthető. (Amúgy ha nem idézőjelet " - hanem aposztrófot ' használsz a grep paraméterénél, akkor megspórolod a backslash használatát.) Amógy nem tudom ezt akartad-e, de azt írtad, hogy a gcc fordítson le minden .c-re végződő fájlt, és az összesből csináljon egyetlen binárist (ami a.out néven jön létre az adott könyvtárban).
- A hozzászóláshoz be kell jelentkezni
Igen, ez volt a célom a paranccsal.
A forráskód más rendszeren lefordul, és működik.
Az aposztrofos trükkre: köszi.
- A hozzászóláshoz be kell jelentkezni
'más rendszeren'
vannak mindenféle helperek, amik néhány tipikus hibát megengedhetõvé tesznek. a gcc egy párat tud, más fordító másik párat.
A legtöbbször valami integrált editor-fordító-linker-debugger-projectkezelõvel találkozik az ember, ami nagyon kényelmessé teszi a munkát, azonban eltakarja a dolgok mûködését.
Pl a gcc az integrált linker és fordító. Neked most ez is baj.
Ahol a fenti példa lefordult, ott kellett lennie egy integrált projectkezelõnek is valahol a rendszerben.
- A hozzászóláshoz be kell jelentkezni
OT: Szerintem amit kerdeztel arra mar kaptal valaszt, de azt hadd jegyezzem meg, hogy valoszinuleg az stdio-t nem a local include-ok kozott akartad megadni. Szoval azt nem idezojelek, hanem kacsacsorok kozott illik irni.
- A hozzászóláshoz be kell jelentkezni