mikrocontroller.net

Forum: Compiler & IDEs stm32 / gcc - Eingebaute printf übergehen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Safari (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

die eingebaute printf-Funktion des gcc ist riesig (~30k), deshalb 
benutze ich schon eine Weile eine Kleinere*.

Angenommen ich habe eine printf-Funktion, die "my_printf" benannt ist.
Nun möchte ich eine Wrapper-Funktion schreiben, die "printf" benannt 
ist.
Ich möchte nun printf, sprintf und snprintf der library übergehen, 
jedoch nicht die ganze library abschalten (z.B. strlen will ich 
behalten).

Wie kann ich das bewerkstelligen?

*hier ein paar Implementationen:
https://github.com/cjlano/tinyprintf
https://github.com/trini/u-boot/blob/master/lib/tiny-printf.c
https://github.com/mpaland/printf
http://www.xappsoftware.com/wordpress/2011/01/17/a-tiny-printf-for-embedded-systems/
http://www.firefly-power.de/ARM/printf.html

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Stichwort dürfte hier "weak linkage" heißen. Damit kann man eine in 
einer Library verwendete Funktion durch eine andere ersetzen, ohne auf 
die Library verzichten zu müssen.

Voraussetzung ist, daß "printf" in Deiner Standardlibrary als "weak 
symbol" definiert ist, das musst Du also gegebenenfalls anpassen.

http://www.valvers.com/programming/c/gcc-weak-function-attributes/

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einfach die neue printf in eine Datei packen und mitlinken reicht aus. 
Die Version aus der libc wird nur genommen, wenn keine andere vorhanden 
ist.

Autor: Safari (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das weak linkage, was Rufus schrieb, wird bei mir der Fall sein. Denn, 
wenn ich es so mache, wie foobar schrieb, wird mein printf-wrapper 
verwendet.

Wenn die library-Funktion nicht "weak" ist, dann bekomme ich mit diesem 
Code eine Fehlermeldung a la "already defined", oder?

Vielen Dank für den Denkanstoss, das hat mir schon einiges an 
Kopfzerbrechen bereitet.

Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Safari schrieb:
> Wenn die library-Funktion nicht "weak" ist, dann bekomme ich mit diesem
> Code eine Fehlermeldung a la "already defined", oder?

Nein.

Der Linker holt beim Linken nur die Symbole aus einer Library, die er zu 
dem Zeitpunkt (die Reihenfolge in der Kommandozeile spielt da eine 
Rolle) noch nicht resolved hat. Wenn Du ihm also früher schon (in einer 
Objektdatei, z.B.) ein passendes Symbol anbietest, sucht in in der 
Library gar nicht erst danach.

"Weak"-Symbole braucht man eigentlich nur (dynamisches Linken, das bei 
der µC-Programmierung keine Rolle spielt, mal aussen vorgelassen), wenn 
man eine Default-Implementierung anbieten, aber dem Anwender eine 
Möglichkeit geben will, seine eigene Spezialisierung mitzubringen bzw. 
den Default zu überschreiben (wie z.B. im Startup-Code).

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem "weak-linkage" ist, wie GNU das typische Verhalten 
implementiert und erweitert hat.

Wenn der Linker nen Symbol sucht, nimmt er die erste Definition, die er 
findet. Dabei wird nicht nur ein Symbol, sondern das gesamte o-File 
dazugelinkt, in dem das Symbol gefunden wurde. Definiert ein o-File 
mehrere Symbole, kann es zu dem "double-defined"-Fehler kommen[1]. Die 
herkömmliche Lösung ist, jedes exportierte Symbol in ein eigenes o-File 
zu packen (d.h. ein File für strlen, eins für strcpy, eins für strncpy, 
etc).

Mit dem weak/strong Attribut hat GNU das Linken erweitert, indem es 
jedem Symbol noch ne Priorität mitgibt. Die Symbole in normalen c-Files 
sind strong, die in Libraries typischerweise weak. Kommen dann ein 
strong und ein oder mehrere weak-Symbole zusammen, gibt es keine 
Fehlermeldung mehr, sondern das strong gewinnt. D.h. aber nicht, dass 
nicht beide Versionen im Programm vorhanden sind, es wird halt nur die 
strong Version benutzt (neuere Linker können unter bestimmten Umständen 
unbenutzte Funktionen wegoptimieren, das ist aber ne weitere 
GNU-Extension).

Normalerweise braucht man sich darum nicht zu kümmern - es klappt 
einfach. Wenn die double-defined Meldung kommt, stimmt normalerweise in 
deinem Programm was nicht und sollte genauer untersucht werden.



[1] Beispiel: strcpy und strncpy sind in einem .o-File im clib. Du 
definierst dir dein eigenes strncpy, das explizit mitgelinkt wird (in 
z.b. mystrncpy.o). Wenn dein Programm nun strcpy (ohne n) benutzt, 
holt der Linker das aus dem clib, leider zusammen mit dem clib-strncpy, 
das ja im gleichen File ist. Peng, double defined strncpy.

Autor: Safari (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die ausführlichen Erklärungen. Nun kann ich ruhigen 
Gewissens diverse Funktionen ersetzen und weiss um das Verhalten des 
Linkers.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.