GCC: Leeres Programm == 23202 Bytes?

Lesezeit: 7 Minuten

Benutzer-Avatar
George

test.c:

int main()
{
    return 0;
}

Ich habe keine Flags verwendet (ich bin ein Neuling bei gcc), nur den Befehl:

gcc test.c

Ich habe die neueste verwendet TDM-Build von GCC auf win32. Die resultierende ausführbare Datei ist fast 23 KB groß, viel zu groß für ein leeres Programm.

Wie kann ich die Größe der ausführbaren Datei reduzieren?

  • Ein Vorschlag: Erhalten Sie die gleichen Ergebnisse mit dem minGW-Build von GCC? Ich bin mir nicht sicher, ob diese Größe ungewöhnlich ist oder nicht, da ich auch nicht sehr an C++ gewöhnt bin.

    – Macha

    22. August 2009 um 13:00 Uhr

  • Versuchen Sie “strip” auf der ausführbaren Datei.

    – Johannes Schaub – litb

    22. August 2009 um 13:10 Uhr

  • Wie genau sind 23 KB “viel zu groß”? Müssen Sie die ausführbare Datei ausdrucken oder so? Wie genau ist das ein Problem? Da das Programm im Grunde leer ist, sind diese 23 KB effektiv ein einmaliger Kostenfaktor. Das bedeutet nicht, dass ein etwas größeres Programm 46 KB belegt. Angenommen, Ihr Programm wächst auf, sagen wir, 5 MB, warum sollten Sie das überhaupt tun? Pflege über die Reduzierung der Größe um 23 KB?

    – jalf

    22. August 2009 um 16:15 Uhr

  • 1. Weil ich an der Feinabstimmung des Kompilierungsprozesses interessiert bin, 2. weil ich wusste, dass der normale Overhead nicht ~23 KB betragen sollte, 3. weil ich es kann.

    – George

    22. August 2009 um 16:22 Uhr

  • Ich verstehe die ganzen negativen Gegenreaktionen auf diese Frage nicht. Auch wenn es für Ihre Anwendungen nicht relevant ist, kann es für andere relevant sein, insbesondere für Entwickler eingebetteter Systeme. Und selbst wenn Sie sich entscheiden, nichts gegen diesen aufgefüllten Code zu unternehmen, kann es dennoch aufschlussreich sein, zu verstehen, warum er vorhanden ist. Obwohl es sich um eine andere Umgebung/ein anderes Toolset handelt, empfehle ich diesen Artikel: msdn.microsoft.com/en-us/magazine/cc301696.aspx

    – Adrian McCarthy

    25. August 2009 um 23:04 Uhr

Folgen Sie nicht seinen Vorschlägen, aber lesen Sie zur Unterhaltung diese Geschichte’ über das Erstellen der kleinstmöglichen ELF-Binärdatei.

  • Scheiße, das war nicht ernst zu nehmen. Es ist jetzt die am meisten positiv bewertete Antwort, die ich gegeben habe!

    – Phil Müller

    23. August 2009 um 1:44 Uhr

  • Interessant ist auch der unter stackoverflow.com/questions/553029/… verlinkte Artikel.

    – bk1e

    23. August 2009 um 16:13 Uhr

  • @Novelocrat Ja, ich habe positiv abgestimmt, weil der von Ihnen gepostete Link sehr interessant war, nicht weil ich denke, dass das OP so etwas tun sollte. ich Hoffnung Die meisten anderen Upvotes waren aus dem gleichen Grund.

    – Tyler McHenry

    24. August 2009 um 15:54 Uhr

  • Schließlich hat eine andere Antwort von mir dies übertroffen. Jetzt muss ich mich nicht mehr so ​​schämen.

    – Phil Müller

    17. Juni 2013 um 19:13 Uhr

Wie kann ich seine Größe reduzieren?

  • Tu es nicht. Du verschwendest nur deine Zeit.
  • Verwenden Sie das Flag -s, um Symbole zu entfernen (gcc -s)

Benutzer-Avatar
Kirill V. Ljadwinski

Standardmäßig sind einige Standardbibliotheken (z. B. C-Runtime) mit Ihrer ausführbaren Datei verknüpft. Schlüssel auschecken --nostdlib --nostartfiles --nodefaultlib für Details. Verknüpfungsmöglichkeiten beschrieben hier.

Für ein echtes Programm ist die zweite Option, es zu versuchen OptimierungsmöglichkeitenzB -Os (auf Größe optimieren).

  • Das stimmt. Diese Schlüssel habe ich nur für eingebettete Systeme verwendet.

    – Kirill W. Ljadwinski

    22. August 2009 um 13:14 Uhr

  • Was empfehlen Sie für den Anfang? (Ich bin neu bei GCC, aber ich habe C schon oft in VisualCpp verwendet.)

    – George

    22. August 2009 um 13:17 Uhr

  • Wenn Sie mit C vertraut sind, ist es angebracht, damit zu beginnen, die Unterschiede zwischen gcc und VisualCpp zu lernen.

    – Kirill W. Ljadwinski

    22. August 2009 um 13:20 Uhr

  • Genau Kristof. Es ist ziemlich sinnlos. Zu lernen, wie man leere Programme so klein wie möglich macht, bedeutet nicht unbedingt, dass man weiß, wie man nicht-triviale Programme klein macht. Alles, was Ihnen bleibt, ist ein Haufen leerer Programme. Konzentrieren Sie sich darauf, etwas zu bekommen Wert Feinabstimmung, zuerst.

    – Rob Kennedy

    22. August 2009 um 16:33 Uhr

Aufgeben. Unter x86-Linux erzeugt gcc 4.3.2 eine 5K-Binärdatei. Aber warte! Das ist mit dynamischer Verlinkung! Das statisch verknüpfte Binärdatei ist über ein halbes Megabyte: 516K. Entspannen Sie sich und lernen Sie, mit dem Aufblähen zu leben.

Und sie sagten, Modula-3 würde wegen einer 200.000-Hello-World-Binärdatei niemals irgendwo hingehen!


Falls Sie sich fragen, was los ist, die Gnu C-Bibliothek ist so strukturiert, dass sie bestimmte Funktionen enthält, unabhängig davon, ob Ihr Programm davon abhängt oder nicht. Zu diesen Funktionen gehören Kleinigkeiten wie malloc und free, dlopen, etwas String-Verarbeitung und vieles mehr ein Kübel voll Dinge, die mit Locales und Internationalisierung zu tun zu haben scheinen, obwohl ich keine relevanten Manpages finden kann.

Das Erstellen kleiner ausführbarer Dateien für Programme, die minimale Dienste erfordern, ist nicht ein Gestaltungsziel für glibc. Um fair zu sein, war es das auch nicht ein Designziel für jedes Laufzeitsystem, mit dem ich je gearbeitet habe (ungefähr ein halbes Dutzend).

Benutzer-Avatar
Wim ten Brink

Wenn Ihr Code nichts tut, ist es überhaupt fair, dass der Compiler trotzdem eine ausführbare Datei erstellt? 😉

Nun, unter Windows hätte jede ausführbare Datei immer noch eine Größe, obwohl sie angemessen klein sein kann. Mit dem alten MS-DOS-System würde eine vollständige Do-Nothing-Anwendung nur ein paar Bytes umfassen. (Ich denke, vier Bytes, um den 21-Stunden-Interrupt zum Schließen des Programms zu verwenden.) Andererseits wurden diese Anwendungen direkt in den Speicher geladen. Als das EXE-Format populärer wurde, änderten sich die Dinge ein wenig. Ausführbare Dateien hatten jetzt zusätzliche Informationen über den Prozess selbst, wie die Verschiebung von Code- und Datensegmenten sowie einige Prüfsummen und Versionsinformationen. Die Einführung von Windows fügte dem Format einen weiteren Header hinzu, um MS-DOS mitzuteilen, dass es die ausführbare Datei nicht ausführen konnte, da sie unter Windows ausgeführt werden musste. Und Windows würde es ohne Probleme erkennen. Natürlich wurde das ausführbare Format auch um Ressourceninformationen wie Bitmaps, Icons und Dialogformulare und vieles mehr erweitert.

Eine ausführbare Do-Nothing-Datei wäre heutzutage zwischen 4 und 8 Kilobyte groß, abhängig von Ihrem Compiler und jeder Methode, die Sie verwendet haben, um ihre Größe zu reduzieren. Es wäre bei einer Größe, bei der UPX tatsächlich zu größeren ausführbaren Dateien führen würde! Möglicherweise werden zusätzliche Bytes in Ihrer ausführbaren Datei hinzugefügt, weil Sie Ihrem Code bestimmte Bibliotheken hinzugefügt haben. Insbesondere Bibliotheken mit initialisierten Daten oder Ressourcen werden eine beträchtliche Menge an Bytes hinzufügen. Das Hinzufügen von Debug-Informationen erhöht auch die Größe der ausführbaren Datei.

Aber während dies alles eine nette Übung zum Reduzieren der Größe ist, könnten Sie sich fragen, ob es praktisch ist, sich einfach weiterhin Gedanken über das Aufblähen von Anwendungen zu machen. Moderne Festplatten teilen Dateien in Segmente auf, und bei wirklich großen Festplatten wäre der Unterschied sehr gering. Der Aufwand, der erforderlich wäre, um die Größe so klein wie möglich zu halten, verlangsamt jedoch die Entwicklungsgeschwindigkeit, es sei denn, Sie sind ein erfahrener Entwickler, der an diese Optimierungen gewöhnt ist. Diese Art von Optimierungen verbessern die Leistung in der Regel nicht, und angesichts des durchschnittlichen Speicherplatzes der meisten Systeme sehe ich nicht ein, warum dies praktisch wäre. (Trotzdem optimiere ich meinen eigenen Code auf ähnliche Weise, aber andererseits habe ich Erfahrung mit diesen Optimierungen.)


Interessiert an EXE-Header? Es beginnt mit den Buchstaben MZ, für „Mark Zbikowski“. Der erste Teil ist der MS-DOS-Header im alten Stil für ausführbare Dateien und wird als Stub für MS-DOS verwendet, der besagt, dass das Programm ist nicht eine ausführbare MS-DOS-Datei. (In der Binärdatei finden Sie den Text “Dieses Programm kann nicht im DOS-Modus ausgeführt werden.”, was im Grunde alles ist, was es tut: diese Nachricht anzeigen. Als nächstes kommt der PE-Header, den Windows erkennt und anstelle von MS-DOS verwendet Header Es beginnt mit den Buchstaben PE für Portable Executable. Nach diesem zweiten Header befindet sich die ausführbare Datei selbst, die in mehrere Code- und Datenblöcke unterteilt ist. Der Header enthält spezielle Neuzuordnungstabellen, die dem Betriebssystem mitteilen, wo ein bestimmter Block geladen werden soll. Und wenn Sie dies in Grenzen halten können, kann die endgültige ausführbare Datei kleiner als 4 KB sein, aber 90 % wären dann Header-Informationen und keine Funktionalität.

  • Bei einer DOS-Anwendung reicht ein einfaches ret aus. Das heißt, 1 Byte.

    – Bruno Reis

    22. August 2009 um 14:45 Uhr

  • Ein Ret würde genügen, aber die offizielle Regel lautete, dass Sie den „Exit“-Interrupt aufrufen mussten.

    – Wim ten Brink

    22. August 2009 um 15:29 Uhr

  • Ich habe mit VS2005 echte ausführbare Windows-Dateien (PE-Format) erstellt, die nützliche Dinge in <4 KB tun. Eine ausführbare Do-Nothing-Datei muss also sicherlich nicht 8 KB groß sein. (Warum? Autorun-Checker für eine CD, starten Sie keine große Installer-EXE, wenn die App bereits installiert ist)

    – MSalter

    24. August 2009 um 8:22 Uhr

  • Der Code tut nichts – er gibt Null an die Umgebung zurück.

    – Jonathan Leffler

    25. August 2009 um 0:45 Uhr

Benutzer-Avatar
Sinan Ünür

Ich mag übrigens die DJGPP FAQ darauf eingegangen vor vielen vielen Jahren:

Im Allgemeinen ist es bedeutungslos, die Codegröße anhand der Größe von „Hallo“-Programmen zu beurteilen, da solche Programme hauptsächlich aus dem Startcode bestehen. … Der größte Teil der Leistung all dieser Funktionen wird in “Hello”-Programmen verschwendet. Es hat keinen Sinn, den ganzen Code auszuführen, nur um eine 15-Byte-Zeichenfolge auszugeben und zu beenden.

  • Bei einer DOS-Anwendung reicht ein einfaches ret aus. Das heißt, 1 Byte.

    – Bruno Reis

    22. August 2009 um 14:45 Uhr

  • Ein Ret würde genügen, aber die offizielle Regel lautete, dass Sie den „Exit“-Interrupt aufrufen mussten.

    – Wim ten Brink

    22. August 2009 um 15:29 Uhr

  • Ich habe mit VS2005 echte ausführbare Windows-Dateien (PE-Format) erstellt, die nützliche Dinge in <4 KB tun. Eine ausführbare Do-Nothing-Datei muss also sicherlich nicht 8 KB groß sein. (Warum? Autorun-Checker für eine CD, starten Sie keine große Installer-EXE, wenn die App bereits installiert ist)

    – MSalter

    24. August 2009 um 8:22 Uhr

  • Der Code tut nichts – er gibt Null an die Umgebung zurück.

    – Jonathan Leffler

    25. August 2009 um 0:45 Uhr

Benutzer-Avatar
Michael Köhne

Was ist der Zweck dieser Übung?

Selbst bei einer so niedrigen Programmiersprache wie C müssen noch viele Einstellungen vorgenommen werden, bevor main aufgerufen werden kann. Ein Teil dieses Setups wird vom Loader gehandhabt (der bestimmte Informationen benötigt), ein Teil wird vom Code gehandhabt, der main aufruft. Und dann gibt es wahrscheinlich ein bisschen Bibliothekscode, den jedes normale Programm haben müsste. Zumindest gibt es wahrscheinlich Verweise auf die Standardbibliotheken, wenn sie in DLLs enthalten sind.

Die Untersuchung der binären Größe des leeren Programms ist an und für sich eine wertlose Übung. Es sagt dir nichts. Wenn Sie etwas über die Codegröße lernen möchten, versuchen Sie, nicht leere (und vorzugsweise nicht triviale) Programme zu schreiben. Vergleichen Sie Programme, die Standardbibliotheken verwenden, mit Programmen, die alles selbst erledigen.

Wenn Sie wirklich wissen wollen, was in dieser Binärdatei vor sich geht (und warum sie so groß ist), dann finden Sie das ausführbare Format heraus, besorgen Sie sich ein Binär-Dump-Tool und nehmen Sie das Ding auseinander.

  • Da Sie die Beweggründe des OP nicht kennen, ist das einfach nicht wahr. Er könnte daran interessiert sein, in die eingebettete Entwicklung einzusteigen, wo beispielsweise die Codegröße eine große Rolle spielt.

    – Phil Müller

    22. August 2009 um 14:06 Uhr

  • Die Codegröße des leeren Programms ist immer noch völlig irrelevant. Und wenn er sich für Embedded-Programmierung interessiert, bei der es auf die Größe des Programms ankommt, dann ist alles, was er mit einem Windows-Compiler herumspielt, irrelevant.

    – Michael Köhne

    22. August 2009 um 14:57 Uhr

  • Die Codegröße eines leeren Programms ist nicht unerheblich, wenn 1. Sie Demos codieren, 2. Sie daran interessiert sind, wie die Kompilierung funktioniert, was in der endgültigen ausführbaren Datei endet, 3. und schließlich, wenn Sie wissen, dass ein leeres Programm nicht ~ sein sollte 23 KB. Es mag keine offensichtliche Verwendung von so etwas geben, aber es macht das Lernen über die Compiler-Flags nicht irrelevant.

    – George

    22. August 2009 um 16:27 Uhr

  • Richard, warum codieren Sie leere Programme als Demos? Und wenn Sie nicht wissen, was in der endgültigen ausführbaren Datei ist, woher wissen Sie dann, dass es nicht 23 K sein sollte? Und wenn Sie nicht erfahren haben, warum es 23 K waren, dann liegt es vielleicht daran, dass Sie nie danach gefragt haben.

    – Rob Kennedy

    22. August 2009 um 16:44 Uhr

1146320cookie-checkGCC: Leeres Programm == 23202 Bytes?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy