warum macht der Linker underscores vor die Namen?

#7499460
Lesenswert?

ich versuche ein bestehendes C-Project unter xcode auf dem MAC zu bauen. Der Compiler macht da aus irgendeinem Grund _ vor die Funktionsnamen und der Linker findet die dann nicht. Irgendwie hatte ich das schon Mal, es war irgendwas mit C und C++, habs aber vergessen wie man das umgeht.

Also in einem file der AUfruf irgendwas(13);

in einem anderen File die Definition: void irgendwas(int zahl) ...

und er Linker verlangt dann nach _irgendwas

#7499543
Lesenswert?

Walter S. schrieb:

Also in einem file der AUfruf irgendwas(13);

in einem anderen File die Definition: void irgendwas(int zahl) ...

und er Linker verlangt dann nach _irgendwas

Willst Du von C++-Code aus bspw. C-Funktionen aufrufen? Dann hast Du es mit dem Name-Mangling des C++-Compilers zu tun. Das müsstest Du für die C-Funktionsdeklarationen mit

1
extern "C" {
2
    int CFunction(void);
3
}

ausschalten.

#7499573
Lesenswert?

Wenn der Linker solch einen Symbolnamen nicht findet, wird dem Linker nicht die Objektdatei übergeben, in der das Symbol definiert ist.

Oder das Symbol (hier: die Funktion "irgendwas") ist als /static/ deklariert und ist daher nur innerhalb ihrer "translation unit" sichtbar.

Da der Linker _irgendwas sucht, wird diese Funktion auch nicht aus C++-Code heraus aufgerufen, denn deren Signatur sähe durch das "name mangling" entschieden anders aus.

Es könnte sein, daß die Funktion "irgendwas" aber als C++-Code übersetzt wurde, und daß der Aufrufer sie als C-Code aufrufen will, also genau andersherum als von Wilhelm beschrieben.

Persönliche Seite #7499621
Lesenswert?

Das zusätzliche "leading underscore" in Symbolnamen wird von manchen ABIs vorgeschrieben, d.h. ein Symbolname hat 1 Underscore mehr als auf anderen Plattformen.

So wird ein Object (Funktion oder Variable), das auf C-Ebene sym heißt, im Assembly als _sym ausgegeben. Beispiel C:

1
int var;
2

3
int fun (void)
4
{
5
    return var;
6
}

wird assembliert mit x686-w64-mingw32-gcc (unbedeutende Teile entfernt):

1
  .globl  _fun
2
_fun:
3
  movl  _var, %eax
4
  ret
5

6
  .globl  _var
7
  .bss
8
_var:
9
  .space 4

Und das gilt dann auch für C++:

fun wird in MinGW als __Z3funv assembliert, für x86_64-linux-gnu hingegen als _Z3funv.

Was unter MinGW auffällt, ist dass Labels zum Beispiel "L5" heißen, was ohne Underscore dann mit einem Objekt namens "L5" verwechselt werden würde. Das ABI vermeidet dies, indem Symbole von Hochsprache einen "_" verpasst bekommen.

Auf anderen Plattformen werden Labels z.B. als ".L5" benamt; keine Ahnung warum das unter Windows nicht gemacht wird / wurde. Evtl. kann ein Archäologe da mehr zu sagen.


Um in einem Project C und C++ zusamme zu nutzen müssen die C-Teile als extern "C" Linkage implementiert sein, im obigen Beispiel etwa

1
extern "C" int fun (void);

Um Assembly und C/C++ zusammen zu verwenden, muss im Assembly die Naming Convention dem ABI folgen. Es ist zwar möglich, den Assembly Name mit GCC anzugeben, aber dabei wird man nach Möglichkeit dem ABI folgen, hier als GCC Erweiterung:

1
int fun (void) __asm ("_bar");

Schließlich gibt es je nach Host noch -f[no-]leading-underscore, aber was ABI angeht gilt das eben gesagte.

#7502946
Lesenswert?

Vielen Dank an alle, bin leider erst jetzt wieder dazu gekommen, gleich der erste Post von Bruno war's: ich hatte ja ein Projekt von Linux auf MAC portiert und beim Erstellen in Xcode zwei von an die 30 Quell-Files übersehen und der Linker hat dann natürlich die fehlenden Funktionen bemängelt und mich mit den Underscores vor den Namen verwirrt, jetzt geht's

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren