schusch
Anmeldungsdatum: 2. September 2008
Beiträge: 324
Wohnort: Berlin
|
Hallo, ich habe seit langer Zeit mal wieder ein kleines C-Programm (Datei cparse.c) geschrieben. Normalerweise sollte die Datei automatisch übersetzen. Doch ich erhalte:
| $ make cparse
cc cparse.c -o cparse
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 11
...
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: In Funktion `_start':
(.text+0x20): Nicht definierter Verweis auf `main'
collect2: error: ld returned 1 exit status
make: *** [cparse] Fehler 1
|
Logisch, wenn der Compiler ohne c-Flag aufgerufen wird.
Also versuchen wir:
| $ gcc -c cparse.c -o cparse
$ file cparse
cparse: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ ./cparse
bash: ./cparse: Keine Berechtigung
$ ls -l cparse
-rw-rw-r-- 1 a0061731 a0061731 930 Feb 9 21:51 cparse
$ chmod +x cparse
$ ./cparse
bash: ./cparse: cannot execute binary file: Fehler im Format der Programmdatei
$
|
Bin gerade etwas ratlos.
|
lubux
Anmeldungsdatum: 21. November 2012
Beiträge: 14314
|
schusch schrieb: bash: ./cparse: cannot execute binary file: Fehler im Format der Programmdatei
$
Wie sind die Ausgaben von:
--(file ./cparse)--
und
ldd ./cparse
?
|
pascoli
Anmeldungsdatum: 5. Mai 2008
Beiträge: 124
|
Ich bin ja nicht DER Experte, aber eine ausführbare Datei mit einer Länge von 930 Byte? gcc -c übersetzt vermutlich nur, da muss noch der Linker drüberlaufen.
|
lubux
Anmeldungsdatum: 21. November 2012
Beiträge: 14314
|
pascoli schrieb: gcc -c übersetzt vermutlich nur, da muss noch der Linker drüberlaufen.
Ja, stimmt, ... denn lt. der manpage für gcc:
-c Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the
form of an object file for each source file.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17605
Wohnort: Berlin
|
Was ergibt denn
?
Nicht definierter Verweis auf main'
sieht ja aus, als hättest Du keine (gültige) Mainmethode.
|
schusch
(Themenstarter)
Anmeldungsdatum: 2. September 2008
Beiträge: 324
Wohnort: Berlin
|
Danke für eure Antworten. @lubux
| $ ldd ./cparse
Das Programm ist nicht dynamisch gelinkt
$ file ./cparse
./cparse: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$
|
@pascoli
Klar, du hast recht. Der Versuch mit -c war Quatsch.
muss gehen @user_unknown
| $ fgrep main cparse.c
void main(int argc, char *argv[]) {
$
|
Aber, keine Ahnung was ich vorhin falsch gemacht habe. Jetzt geht es. Ich habe hello.c
| #include <stdio.h>
main()
{
printf("Hello world!\n");
}
|
mit
übersetzt. Alles chic. Danach hat auch
funktioniert. 😬 Die Ausgabe von ldd und file sind nun
| $ file cparse
cparse: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=f4a3631fd2fc0067bb8cbe22358a882bebd3dc5c, not stripped
$ ldd cparse
linux-vdso.so.1 => (0x00007ffd3cbea000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5285838000)
/lib64/ld-linux-x86-64.so.2 (0x00005580a14c8000)
$
|
Immer noch mit einem ? im Gesicht, nochmals Danke für eure Antworten.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
Rückgabewert von main() muss m.E. int sein. Du solltest ihn auf jeden Fall explizit deklarieren.
|
spaghetticode
Anmeldungsdatum: 19. Oktober 2015
Beiträge: 75
|
rklm schrieb: Rückgabewert von main() muss m.E. int sein. Du solltest ihn auf jeden Fall explizit deklarieren.
In C89 war auch main() gültig. void main() ist aber in jedem Fall zu vermeiden.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
spaghetticode schrieb: rklm schrieb: Rückgabewert von main() muss m.E. int sein. Du solltest ihn auf jeden Fall explizit deklarieren.
In C89 war auch main() gültig.
Dann ist int implizit, so hatte ich das jedenfalls in Erinnerung.
void main() ist aber in jedem Fall zu vermeiden.
Ja, das denke ich auch.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17605
Wohnort: Berlin
|
| #include <stdio.h>
void main()
{
printf("Hello world!\n");
}
|
Das müsste aber zu einer ausdrucksstärkeren Fehlermeldung führen, wenn void main nicht legal wäre. Führt es aber nicht, wie man rasch erkennen kann - obiges Programm compiliert anstandslos und lässt sich ausführen wie ein halber Liter Dünnbier nach Frankreich. | gcc ctest.c -o ctest
./ctest
# Hello world!
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 13176
|
user_unknown schrieb:
Das müsste aber zu einer ausdrucksstärkeren Fehlermeldung führen, wenn void main nicht legal wäre.
Stimmt, gcc 4.9.3 warnt nur - und auch nur bei der entsprechenden Einstellung: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | $ gcc -Wall -o a.out x.c
x.c:3:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main()
^
$ cat x.c
#include <stdio.h>
void main()
{
printf("Hello world!\n");
}
$ gcc --version
gcc (GCC) 4.9.3
Copyright (C) 2015 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.
|
Führt es aber nicht, wie man rasch erkennen kann - obiges Programm compiliert anstandslos und lässt sich ausführen wie ein halber Liter Dünnbier nach Frankreich.
Naja, es sind ja nur noch 100ml pro Gebinde erlaubt. 😉
|
spaghetticode
Anmeldungsdatum: 19. Oktober 2015
Beiträge: 75
|
user_unknown schrieb: Das müsste aber zu einer ausdrucksstärkeren Fehlermeldung führen, wenn void main nicht legal wäre.
Müsste es, ja - aber das ist dasselbe wie mit den Webbrowsern und den W3C-Standards Anfang der 2000er - die verbreiteten Compiler fressen fast alles. Das nennt sich dann "convenience", und wie wir ja aus dem Alltag wissen, ist "convenience food" selten was Gutes. Das Problem an void main() ist doch ganz logisch: eine vernünftige Ausführungsumgebung erwartet eine Rückgabe von den Programmen, die sie da so startet. Wenn dann keine kommt, ist das der Ausführungsumgebung selbst vielleicht noch egal - aber dem zweiten Programm, das die Rückgabe verarbeiten möchte, vielleicht schon nicht mehr. Das mag bei "hello world" keine Rolle spielen, ja, vielleicht spielt es gar in über 90% der Fälle keine Rolle. Für die 10%, in denen das aber doch Probleme gibt, für die gibt es deshalb den unabhängigen Standard, der sagt: main() hat gefälligst was zurückzugeben. Man muss sicherlich, gerade als Hobbyprogrammierer, wie ich einer bin, nicht päpstlicher sein als der Papst. Aber eine Sprache wie C oder C++ sollte man, wenn schon, dann auch richtig lernen. Dazu gehört auch das Kompilieren mit allen Warnungen und Strenge-Optionen. Dann würde gcc nämlich bei void man() sehr wohl meckern.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17605
Wohnort: Berlin
|
spaghetticode schrieb: user_unknown schrieb: Das müsste aber zu einer ausdrucksstärkeren Fehlermeldung führen, wenn void main nicht legal wäre.
Müsste es, ja - aber das ist dasselbe wie mit den Webbrowsern und den W3C-Standards Anfang der 2000er - die verbreiteten Compiler fressen fast alles.
Nur dass es der Linker ist, der sich beschwert.
Das Problem an void main() ist doch ganz logisch: eine vernünftige Ausführungsumgebung erwartet eine Rückgabe von den Programmen, die sie da so startet. Wenn dann keine kommt, ist das der Ausführungsumgebung selbst vielleicht noch egal - aber dem zweiten Programm, das die Rückgabe verarbeiten möchte, vielleicht schon nicht mehr. Das mag bei "hello world" keine Rolle spielen, ja, vielleicht spielt es gar in über 90% der Fälle keine Rolle. Für die 10%, in denen das aber doch Probleme gibt, für die gibt es deshalb den unabhängigen Standard, der sagt: main() hat gefälligst was zurückzugeben.
Umgekehrt wird ein Schuh draus. Wenn man etwas zurückgeben will, dann kann man es tun und wird es auch tun. Wenn nicht, dann gibt man auch nichts sinnvolles zurück, sondern schreibt return 0; oder was immer hin, um die Tools stillzustellen.
Man muss sicherlich, gerade als Hobbyprogrammierer, wie ich einer bin, nicht päpstlicher sein als der Papst. Aber eine Sprache wie C oder C++ sollte man, wenn schon, dann auch richtig lernen. Dazu gehört auch das Kompilieren mit allen Warnungen und Strenge-Optionen. Dann würde gcc nämlich bei void man() sehr wohl meckern.
Durch den zweiten Block, wo gcc genutzt wird, habe ich übersehen, dass oben cc genutzt wird - den habe ich nicht da.
|
spaghetticode
Anmeldungsdatum: 19. Oktober 2015
Beiträge: 75
|
user_unknown schrieb: Umgekehrt wird ein Schuh draus. Wenn man etwas zurückgeben will, dann kann man es tun und wird es auch tun. Wenn nicht, dann gibt man auch nichts sinnvolles zurück, sondern schreibt return 0; oder was immer hin, um die Tools stillzustellen.
Ähm... return 0 ist eine (sinnvolle!) Rückgabe. Und ganz sicher nicht void. EDIT: Hier mehr zum Thema: http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284376&answer=1044841143
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17605
Wohnort: Berlin
|
spaghetticode schrieb: Ähm... return 0 ist eine (sinnvolle!) Rückgabe. Und ganz sicher nicht void.
Wenn return 0 immer eine sinnvolle Rückgabe wäre, dann müsste man es nicht hinschreiben sondern könnte es zum default machen, oder?
|