Forum: Compiler & IDEs /lib/i386-linux-gnu/libc.so.6: version `GLIBC_2.28' not found


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.
von Bauform B. (bauformb)


Lesenswert?

Mahlzeit!

kann man auf einem aktuellen Debian ein C-Programm so übersetzen, dass 
es auch auf Rechnern mit alter libc läuft? Tritt das Problem auch bei 
libX11.so usw. auf?

Die offensichtliche Lösung, den alten Kisten endlich ein Update zu 
gönnen, kommt offensichtlich nicht in Frage (sind nicht meine). Zur Zeit 
benutze ich zum Übersetzen so einen alten Rechner, aber der ist soo 
laaangsam...

von Vulganer (Gast)


Lesenswert?

Containerless Container (vulgo: statisch gelinkt) zu verwenden wäre eine 
Möglichkeit.

von Bauform B. (bauformb)


Lesenswert?

danke, eigentlich naheliegend, aber praktisch ziemlich aussichtslos:
1
warning:
2
Using 'getaddrinfo' in statically linked applications requires at
3
runtime the shared libraries from the glibc version used for linking

von Klaus S. (kseege)


Lesenswert?

Bauform B. schrieb:
> danke, eigentlich naheliegend, aber praktisch ziemlich
> aussichtslos:warning:
> Using 'getaddrinfo' in statically linked applications requires at
> runtime the shared libraries from the glibc version used for linking

Sehr lustig :-))))

Nach meinem Halbwissen braucht man "getaddrinfo" nur für dynamisch 
gelinkte  Libraries. Für statische schaut der Compiler. Wozu sollte da 
irgendwer "getaddrinfo" aufrufen?

Gruß Klaus (der soundsovielte)

von Bauform B. (bauformb)


Lesenswert?

Klaus S. schrieb:
> Wozu sollte da irgendwer "getaddrinfo" aufrufen?

die da war es, aber wozu werden wir nie erfahren...

libX11.a(xim_trans.o): in function `_XimXTransSocketINETConnect'

von Frank K. (fchk)


Lesenswert?

Bauform B. schrieb:

> Die offensichtliche Lösung, den alten Kisten endlich ein Update zu
> gönnen, kommt offensichtlich nicht in Frage (sind nicht meine). Zur Zeit
> benutze ich zum Übersetzen so einen alten Rechner, aber der ist soo
> laaangsam...

Dann sperre doch die alte Installation in eine VirtualBox oder KVM-QEMU 
auf aktueller Hardware. Dann ist es auch schnell.

fchk

von Klaus S. (kseege)


Lesenswert?

Bauform B. schrieb:
>> Wozu sollte da irgendwer "getaddrinfo" aufrufen?
> die da war es, aber wozu werden wir nie erfahren...

Ist der Versuch, statisch zu linken, damit endgültig gescheitert? Finde 
den Versuch dazu hochgradig interessant, weil ich der Meinung bin, daß 
Linux erst dann desktoptauglich wird, wenn statisches Linken genauso 
einfach wird wie dynamisches. Meine eigenen Versuche dazu sind 
jedenfalls alle gescheitert.

Gruß Klaus (der soundsovielte)

von Vulganer (Gast)


Lesenswert?

Wie macht das eigentlich Golang?
Denn Golang produziert per default statisch gelinkte Binarys.

Ansonsten bliebe nur das ersetzen von getaddrinfo() gegen was eigenes.

von Bauform B. (bauformb)


Lesenswert?

Frank K. schrieb:
> KVM-QEMU auf aktueller Hardware

das hatte ich schon mal aufgegeben, aber da wollte ich das komplette 
alte System laufen lassen. Rein als "Build-Server" sollte es einfach 
sein, muss ich nochmal probieren, danke.

Klaus S. schrieb:
> Ist der Versuch, statisch zu linken, damit endgültig gescheitert? Finde
> den Versuch dazu hochgradig interessant, weil ich der Meinung bin, daß
> Linux erst dann desktoptauglich wird, wenn statisches Linken genauso
> einfach wird wie dynamisches.

Speziell für dieses Programm probiere ich nicht weiter. Eine reine 
Consolen-Anwendung läuft aber. Bei der habe ich nur dem gcc ein -static 
mit gegeben und die Funktionen aus meiner shared lib direkt dazu 
gelinkt. Wenn sich -static bewährt, würde ich aus der lib.so natürlich 
eine lib.a machen.

Der nächste Versuch wäre ein GTK-Programm. Das setzt auf X11 auf und 
dürfte genau wie der erste Versuch daran scheitern. X11 funktioniert ja 
per Netzwerk.

In einer alten rinetd.conf steht ein Kommentar
1
# hostnamen gehen nicht, wenn rinetd statisch gelinkt ist
 Ich kann mich aber nicht erinnern, ob ich deshalb direkt IP-Adressen 
benutzt habe oder doch einen dynamisch gelinkten rinetd. Irgendwas war 
da, so ganz grob ungefähr "zwecks Performance bietet die libc ein paar 
Netzwerkfunktionen nicht statisch an".

Vulganer schrieb:
> Wie macht das eigentlich Golang?
> Denn Golang produziert per default statisch gelinkte Binarys.

Naja, wer eine ganze Sprache neu baut, kann natürlich ein paar 
Funktionen mitliefern.

von Programmierer (Gast)


Lesenswert?

Eine Möglichkeit eine komplexe Anwendungen mit vielen Abhängigkeiten 
statisch zu linken ist der Paketmanager Conan ( https://conan.io/ ). 
Wenn man in den Optionen für Abhängigkeiten (Gtk+ & Co) "static" angibt, 
wird statisch gelinkt. Das funktioniert allerdings prinzipbedingt nicht 
unbeschränkt, manche Dinge wie OpenGL oder Vulkan müssen die jeweiligen 
Treiber dynamisch laden. Außerdem sind nicht alle Pakete darauf 
vorbereitet, stelle dich auf eine Menge Fummelei ein.

Was m.M.n. die bessere Option ist: Alle benötigten .so's mitliefern. 
Wenn man conan verwendet kann man sich dort alle benötigten .so's in den 
Build-Ordner kopieren lassen, dann kopiert man sich noch die libc.so 
dazu, und fertig ist das komplette Anwendungspaket was so ziemlich 
überall laufen sollte.

von Bauform B. (bauformb)


Lesenswert?

Programmierer schrieb:
> Was m.M.n. die bessere Option ist: Alle benötigten .so's mitliefern.

Und dann mit LD_LIBRARY_PATH=/home/user/lib/ oder wie? Irgendwie extrem, 
besonders, was die libc angeht. Das vereinigt die Nachteile von 
statischem und dynamischem Linken, also eine richtig moderne Lösung ;) 
Aber irgendwie auch extrem praktisch und bequem. Führe mich nicht in 
Versuchung...

von Klaus S. (kseege)


Lesenswert?

Bauform B. schrieb:
> Aber irgendwie auch extrem praktisch und bequem. Führe mich nicht in
> Versuchung...

Gobolinux hat genau damit das Problem grundsätzlich zu lösen versucht. 
Hat aber wohl nicht viel Anklang gefunden, ist wohl zu einfach.

Gruß Klaus (der soundsovielte)

von Programmierer (Gast)


Lesenswert?

Bauform B. schrieb:
> Und dann mit LD_LIBRARY_PATH=/home/user/lib/ oder wie?

Ja genau. Am besten in ein "start.sh" script wrappen o.ä. Ist aus 
technischer Sicht nicht gerade sauber, aber eben pragmatisch und 
funktioniert gut. Da Speicher mittlerweile billig ist tut es auch nicht 
allzu weh die Bibliotheken ggf. mehrfach auf der Platte zu haben.


Bauform B. schrieb:
> Führe mich nicht in Versuchung...

Naja, irgendwo muss man auch mal ans Ziel kommen. Da die Linux-Community 
nicht dazu in der Lage ist dafür eine vernünftige Lösung zu finden 
(außer alles in den Package Manager zu stellen und zu hoffen dass ein 
Maintainer es am Leben hält, super für proprietäre oder 
Spezial-Software). Man kann ja die .so's immer noch löschen und hoffen, 
dass es mit dem System-Libs funktioniert. Die .so's zusammen mit der 
Anwendung aufzubewahren ist schon eine gute Idee für die 
Langzeit-Verfügbarkeit. Die Linux-Kernel-APIs hingegen sind sehr stabil.

Android macht es letztlich genauso, alle Apps liefern alle ihre 
Abhängigkeiten in der .apk Datei mit. Man kann keine Libraries einzeln 
installieren und Android selber bietet einen definierten versionierten 
Satz an APIs. Das ist zwar auch Speicherverschwendung weil so ziemlich 
jede App z.B. die AndroidX Library mitliefert, aber es ist sehr 
erfolgreich; weil es eben super einfach ist Apps zu installieren und es 
keine Abhängigkeitshölle gibt. So lustige Paket-Konflikt-Situationen wie 
sie unter den klassischen Distros auftreten können gibt's unter Android 
nicht.

von MaWin (Gast)


Lesenswert?

Du kannst auch eine alte Version deines OS in einem chroot installieren. 
Bei Debian geht das einwandfrei. Man kann dort dann zum Beispiel ein 
aktuelles 64bit Debian als OS fahren und im chroot ein altes 32bit.

von Gerd E. (robberknight)


Lesenswert?

Schau Dir mal AppImage an. Da werden die Binaries so gebaut, daß sie 
alle Shared Libraries gepackt mitbringen. Beim Start wird das dann alles 
ausgepackt und über einen relativen Pfad geladen.

von Bauform B. (bauformb)


Lesenswert?

ja, was es alles gibt, danke. Dabei fällt mir ein, früher hat man qemu 
und ein Image von der alten Platte genommen und fertig war die VM. Wenn 
das immer noch so läuft, ist das doch konkurenzlos einfach. 
Angeblich/theoretisch würde das gleiche Image sogar unter Windows 
funktionieren.  Nicht für mich, aber für manche Leute mit Laptop könnte 
das ein Argument sein.

von Weiss Nicht (Gast)


Lesenswert?

Bauform B. schrieb:
> kann man auf einem aktuellen Debian ein C-Programm so übersetzen, dass
> es auch auf Rechnern mit alter libc läuft? Tritt das Problem auch bei
> libX11.so usw. auf?

Im Prinzip braucht man dafür nur den "--sysroot" Parameter des Compilers 
und ein System-image. Das System-Image muss man sich selbst irgendwo 
zusammenbauen, zum Beispiel aus einem Docker-Container mit allem 
benótigtem Zeug (dev-Packages für libc etc.) herauskopieren und danach 
die Symlinks von absolute in relative verwandeln (zB mit 
https://github.com/brandt/symlinks).

Wenn das Programm cmake als Build-System verwendet muss man dann nur 
noch CMAKE_SYSROOT auf den Pfad zum sysimage setzen. Bei autotools dann 
eben "--sysroot" zu den CFLAGS und LDFLAGS hinzufügen. Problematisch ist 
dann nur noch der RPATH für transitive Abhängigkeiten: den muss man ggf. 
via "-Wl,--rpath-link,..." in den LDFLAGS an den Linker weitergeben. Je 
nach Aufbau der Distro gilt es dann noch Unterschiede in der 
Ordner-Struktur zu beachten (multilib, multiarch) und Suchpfade 
entsprechend anzupassen - eventuell muss man sogar den Compiler zum 
Targetting des anderen Systems neu bauen, weil manche Suchpfade fest 
eingebacken sind.

Also, ja, das ist durchaus möglich, erfordert aber uU einiges an Arbeit 
und Túftelei, bis es richtig funktioniert: Im Grunde macht man da ein 
ganz normales cross-compiling von linux zu linux, macht es also im 
Grunde auch nicht anders, als wenn man sich eine toolchain für "system 
X" zusammen baut.

von S. R. (svenska)


Lesenswert?

Bauform B. schrieb:
> kann man auf einem aktuellen Debian ein C-Programm so übersetzen, dass
> es auch auf Rechnern mit alter libc läuft? Tritt das Problem auch bei
> libX11.so usw. auf?

Die Linux-Welt war dafür noch nie vorgesehen, daher lautet die Antwort 
"nein". Es gibt natürlich Workarounds.

Theoretisch könnte man statisch linken, aber glibc hat das noch nie 
sinnvoll unterstützt. Fällt also aus.

Du kannst dein Programm in einer alten Umgebung übersetzen, also chroot, 
docker, VirtualBox o.ä. Oder du tauschst die libc gegen eine, die 
statisch linken kann. Beispielsweise kommt dietlibc mit einem passenden 
Compiler-Wrapper, wo du nur "gcc" gegen "diet gcc" tauschen musst; 
inwieweit das Buildsystem deiner Anwendung damit klarkommt, lässt sich 
schlecht sagen.

Die dritte Option wäre, dein Zielsystem als embedded device zu 
betrachten und eine vollwertige Cross-Compile-Umgebung aufzusetzen. 
Sowas kann buildroot, und es gibt auch einige glibc-Versionen zur 
Auswahl; da fällt dann ein Cross-Compiler bei raus, der für das Target 
passende Binaries erzeugt.

> Die offensichtliche Lösung, den alten Kisten endlich ein Update zu
> gönnen, kommt offensichtlich nicht in Frage (sind nicht meine). Zur Zeit
> benutze ich zum Übersetzen so einen alten Rechner, aber der ist soo
> laaangsam...

Installiere deine alte Software auf einen neuen Rechner (in einer VM), 
das dürfte die einfachste Lösung sein.

Bauform B. schrieb:
>> Was m.M.n. die bessere Option ist: Alle benötigten .so's mitliefern.
> Und dann mit LD_LIBRARY_PATH=/home/user/lib/ oder wie?

Wird dann eklig, wenn manche Teile trotzdem dynamisch bleiben müssen 
(z.B: die oben genannten OpenGL-Dinge) und dann im Extremfall zwei 
malloc-Implementationen den gleichen Speicher zu verwalten versuchen.

Für die libc - insbesondere die glibc - ist das keine wirklich gute 
Lösung, im Gegensatz zu eigenen Bibliotheken.

von Weiss Nicht (Gast)


Lesenswert?

S. R. schrieb:
> Bauform B. schrieb:
>>> Was m.M.n. die bessere Option ist: Alle benötigten .so's mitliefern.
>> Und dann mit LD_LIBRARY_PATH=/home/user/lib/ oder wie?
>
> Wird dann eklig, wenn manche Teile trotzdem dynamisch bleiben müssen
> (z.B: die oben genannten OpenGL-Dinge) und dann im Extremfall zwei
> malloc-Implementationen den gleichen Speicher zu verwalten versuchen.
>
> Für die libc - insbesondere die glibc - ist das keine wirklich gute
> Lösung, im Gegensatz zu eigenen Bibliotheken.

Richtig. Sämtliches Zeug selbst mitausliefern erhöht nur den eigenen 
Wartungsaufwand, da man dann sämtliche Updates von verwendeten Paketen 
immer selbst machen muss, statt die normalen System-Updates der 
Zieldristribution auszunutzen. Man muss auch gar nicht so feingranular 
vorgehen und genau die selbe Version/Distro targetten, da die meisten 
Updates in linux-land rückwärtskompatibel sind. "Hinreichend outdated" 
genügt also.

von Rolf M. (rmagnus)


Lesenswert?

Frank K. schrieb:
> Bauform B. schrieb:
>
>> Die offensichtliche Lösung, den alten Kisten endlich ein Update zu
>> gönnen, kommt offensichtlich nicht in Frage (sind nicht meine). Zur Zeit
>> benutze ich zum Übersetzen so einen alten Rechner, aber der ist soo
>> laaangsam...
>
> Dann sperre doch die alte Installation in eine VirtualBox oder KVM-QEMU
> auf aktueller Hardware. Dann ist es auch schnell.

Auch Docker ist eine Option. Das nutze ich, um Programme für eine alte 
CentOS-Version zu compilieren, die ein Kunde einsetzt. Ich habe einfach 
ein Image der betreffenden Version genommen, darauf basierend alles, was 
ich zum Bauen brauche hinzugefügt, und dann einen Container erstellt, 
aus dem heraus direkt auf das Source-Verzeichnis auf dem "Host" 
zugegriffen werden kann. Da kann ich dann den make-Prozess laufen 
lassen. Das klingt vielleicht kompliziert, ist es aber gar nicht.

von Εrnst B. (ernst)


Lesenswert?

Bauform B. schrieb:
> kann man auf einem aktuellen Debian ein C-Programm so übersetzen, dass
> es auch auf Rechnern mit alter libc läuft?

Nachdem die Bibliotheks-Kompatibilität normalerweise nur "in die andere 
Richtung" gewährleistet wird, wäre die naheliegende Antwort:
Kompilier das Programm auf dem ältesten Debian(-chroot,-container,-vm), 
das du unterstützen willst. Dann wird es auch auf den neueren Versionen 
funktionieren.

d.H. du hast beim Übersetzen einmalig Mehraufwand, aber alle deine 
Anwender kriegen ein sofort lauffähiges Binary.

von S. R. (svenska)


Lesenswert?

Εrnst B. schrieb:
> Kompilier das Programm auf dem ältesten Debian(-chroot,-container,-vm),
> das du unterstützen willst. Dann wird es auch auf den neueren Versionen
> funktionieren.

Das ist auch der Ansatz, den nvidia mit den Binärtreibern fährt.

Weiss Nicht schrieb:
> Sämtliches Zeug selbst mitausliefern erhöht nur den eigenen
> Wartungsaufwand, da man dann sämtliche Updates von verwendeten
> Paketen immer selbst machen muss, statt die normalen System-
> Updates der Zieldristribution auszunutzen.

Das Zielsystem macht offensichtlich schon seit Jahren keine ordentlichen 
Updates mehr...

Programme als Container auszuliefern kommt wieder in Mode. Der Kreis aus 
den 90ern ist jetzt wieder geschlossen, demnächst wird dann 
InstallShield wiederauferstehen.

von Bauform B. (bauformb)


Lesenswert?

Nach einem langen Wochenende muss ich das erstmal vertagen. Vielen Dank 
für die vielen Vorschläge, die gehören alle mal näher untersucht. Also, 
bis später.

Die einfachste Möglichkeit, qemu, funktioniert schon mal nicht. qemu-kvm 
kann anscheinend kein 3dnow und ohne wird es noch langsamer als die alte 
Hardware. Und virtualbox ist bei Debian wegen Oracles Umgang mit 
Sicherheitslücken in Ungnade gefallen.

von S. R. (svenska)


Lesenswert?

Bauform B. schrieb:
> qemu-kvm kann anscheinend kein 3dnow und ohne wird es noch langsamer
> als die alte Hardware.

Wenn deine Host-CPU kein 3DNow! kann, dann kann die Gast-CPU das auch 
nicht (stattdessen bekommst du MMX, SSE, SSE2, SSE3 und evtl. SSE4 - 
einige gab es auch damals schon). Performance-Einbußen solltest du keine 
haben.

Bauform B. schrieb:
> Und virtualbox ist bei Debian wegen Oracles Umgang mit
> Sicherheitslücken in Ungnade gefallen.

Du solltest das alte System ja nicht mit der virtuellen Maschine 
ersetzen, sondern damit nur die alte Software neu bauen können... 
C-Compiler nutzen weder MMX noch 3DNow, sie erzeugen nur Code, der das 
tut.

Mit anderen Worten: Hä? Du erzählst komische Dinge.

von Bauform B. (bauformb)


Lesenswert?

S. R. schrieb:
> Hä

je nun, qemu ist besonders attraktiv, wenn man ein vorhandenes Disk 
Image 1:1 nutzen kann. Wenn das nicht geht, sind alle Lösungen wieder 
gleich auf. Unter diesen Umständen sollte ich wirklich eher für Updates 
auf den alten Rechnern sorgen.

von S. R. (svenska)


Lesenswert?

Und was hat das mit "Qemu kann kein 3DNow!" zu tun?

von Bauform B. (bauformb)


Lesenswert?

Das Disk-Image der alten Rechner funktioniert mit qemu/kvm nicht und 
ohne kvm ist es viel zu langsam. Wahrscheinlich brauche ich "nur" einen 
passenden Kernel im Image, aber das ist, wie alle anderen Lösungen, eben 
viel aufwändiger. Und alles bleibt nur eine Notlösung.

Bei der ursprünglichen Frage hatte ich gehofft, dass man dem Linker (dem 
gcc?) irgendwie sagen könnte "bau das kompatibel zur alten glibc-x.y.z".

von Εrnst B. (ernst)


Lesenswert?

Bauform B. schrieb:
> Bei der ursprünglichen Frage hatte ich gehofft, dass man dem Linker (dem
> gcc?) irgendwie sagen könnte "bau das kompatibel zur alten glibc-x.y.z".

Geht rein theoretisch auch, Ungetestet:

In der Glibc sind seit längerem die Symbole versioniert, und du kannst 
gegen eine spezielle Version linken.

dazu schaust du in der Fehlermeldung (das was du im Thread-Titel 
abgeschnitten hast) nach, welche Funktionen in einer zu neuen Version 
erwartet werden, und packst dann per
__asm__(".symver funktionsname,funktionsname@GLIBC_2.x.y");
für jede störende Version einen entsprechenden Hinweis an den Linker 
dazu.


Edit:
Evtl. ist das über "-Wl,--version-script ..." einfacher zu erreichen, 
damit müsstest du auch die glibc-funktionen auf eine ältere Version 
linken können...

: Bearbeitet durch User
von Bauform B. (bauformb)


Lesenswert?

Εrnst B. schrieb:
> .symver

Faszinierend! Der Mechanismus funktioniert beim ersten Versuch, obwohl 
es im Handbuch¹ so aussieht, als ob .symver nur für die Quellen einer 
lib gedacht ist. Es war nicht einmal Fleißarbeit, weil nur ein einziges 
fcntl() zu neu war. Also genügte eine Zeile in der Quelle, die fcntl() 
benutzt.

Witzigerweise ist das fcntl(fd, F_SETFD, FD_CLOEXEC) wahrscheinlich 
sogar überflüssig. "Neuerdings" benutzt man doch open() mit O_CLOEXEC, 
oder?

Jetzt braucht es noch ein wenig testen und Untergrundforschung, im 
Moment benutzt ein Programm die falsche Konfiguration...

1) http://sourceware.org/binutils/docs/ld/VERSION.html

Edit: es scheint auch mit open(,, O_CLOEXEX) zu laufen, aber 
close-on-exec haben oder nicht gibt hässliche Fehler.

Jedenfalls sieht man mal wieder, das richtig fragen viel schwieriger ist 
als antworten. Vielen Dank!

: Bearbeitet durch User
von Ein T. (ein_typ)


Lesenswert?

Bauform B. schrieb:
> kann man auf einem aktuellen Debian ein C-Programm so übersetzen, dass
> es auch auf Rechnern mit alter libc läuft?

Höchstwahrscheinlich, aber wie Du bereits bemerkt hast, gibt es ein 
Problem mit dem statischen Linken der Resolver-Bibliothek aus der GNU C 
Library. Eine Möglichkeit zur Behebung des Problems war bei mir (vor 
langer, langer Zeit) die Verwendung einer anderen C-Bibliothek -- wenn 
ich mich recht entsinne, habe ich die Software einfach unter Alpine 
Linux übersetzt, das die musl-libC verwendet. Eine andere Alternative 
könnte auch die dietlibc von Felix "Fefe" von Leitner sein. Das ist aber 
alles sehr lange her, meine Ohren sind trüb und meine Erinnerung ist 
grauhaarig. ;-)

> Tritt das Problem auch bei libX11.so usw. auf?

Das käme wohl auf einen Versuch an, schätze ich. HTH, but YMMV.

von Rolf M. (rmagnus)


Lesenswert?

Es gibt noch eine andere Variante: Man liefert die glibc selbst auch 
mit. Dazu muss man allerdings auch den dynamischen Linker 
(ld-linux-x86-64.so.2 oder sowas) manuell aufrufen. Ja, das ist zwar ein 
.so-File, kann aber als Executable auch direkt ausgeführt werden.
Dazu einmal ldd <deinprogramm> machen und alle angezeigten Bibliotheken 
in ein Verzeichnis kopieren. Dann ein Skript machen, das LD_LIBRARY_PATH 
auf dieses Verzeichnis setzt und dann eben das kopierte ld-….so aufruft 
mit dem Executable als Kommandozeilenparameter.

: Bearbeitet durch User

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]
  • [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.

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