C++ Dateigröße immer > 6 kBytes

Fragen zu allen anderen Programmiersprachen.
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Eric hat geschrieben:Falls du es nicht schon machst, könntest du die Optimierung auf -Os stellen (optimiert auf Größe).
Und beim Linker kannst du noch -s angeben (entfernt einige überflüssige Sachen beim Linken)
oder alternativ die Strip.exe von MinGW benutzen. (sollte aufs gleiche hinauslaufen.)
Ist schon alles drin.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

DarkDragon hat geschrieben:Danke für den Tipp :-) . Aber viele Leute behaupten man könne auch ohne "rumdoktorn" mit C++ unter 5 kB kommen.
Hallo DarkDragon,

das hat nichts mit der Sprache C++ zu tun, sondern eher mit dem
Prozess des Kompilierens mit einem bestimmten Compiler(-system).
In Deinem speziellen Fall betrifft es den Linker.

Davon abgesehen ist Dein gezeigter Code nur C, nicht C++.


Ich habe mir jetzt extra mal wieder DevC++ installiert und komme
mit Deinem Code auf eine .EXE von 3kb.
DevC++ Version ist 4.9.9.2 (GCC 3.4.2, LD 2.15.91).

Dazu gibst Du unter "Projekt Optionen > Parameter > Linker"
folgendes ein:

Code: Alles auswählen

-lkernel32
-luser32
-lgdi32
-lopengl32

-s
-nostdlib
--entry _WinMain@16
Die ersten 4 Zeilen teilen dem Linker mit welche Import-Libraries
er verwenden soll. Die ersten 3 sind Standard-WinAPI, die letzte
für OpenGL.
Wenn Du später weitere Libs benutzt, mußt Du die dort hinzufügen,
z.B. "-lglu32", "-lglut32" usw.

Die Linker-Option "-s" nimmt unbenutze Symbole aus dem Ergebniss
heraus.
Damit kommst Du wohl auf ca. 6,5kb.

Die letzten 2 Optionen sind nun entscheidend:
"-nostdlib" teilt dem Linker mit keine Standard-(C/C++)-Bibliotheken
einzufügen. Da Du keine C-Befehle (malloc etc.) benutzt, sondern
nur reines WinAPI, ist das kein Problem.
Mit "--entry _WinMain@16" setzt Du nun den Einsprungspunkt in
Deinem Programm. Dieser ist standardmässig in der Standardbibliothek,
die wir aber vom Linken ausgeschlossen haben.

Wenn Du nun Standard-C-Funktionen verwenden möchtest, dann
wird es zu einem Fehler kommen, da wir die Standardbibliothek
ja nicht benutzen.

Code: Alles auswählen

int *x = (int*)malloc(100);
Hier wird ein Linkerfehler kommen, da die Funktion "malloc" nicht
eingebunden wird. Dafür gibt es verschiedene Workarounds.

In diesem Beispiel könntest Du Dir ein eigenes "malloc" schreiben,
welches dann WinAPI-Funktionen benutzt (Global-/LocalAlloc oder
über die Heap-Funktionen).
Oder Du bindest die DLL "CRTDLL.dll" ein, so wie das auch PureBasic
macht. Wie der Name schon sagt, ist das eine C-Runtime-DLL mit
den C-Funktionen in einer DLL. Diese DLL ist seit Win95 mit dabei,
also überall vorhanden (sonst könnte es PB ja auch nicht verwenden).

Mit anderen C-Funktionen (strlen, printf usw.) ist es genauso.
Entweder selbst schreiben oder aus CRTDLL importieren.
Welche Funktionen enthalten sind findest Du sicherlich im MSDN,
oder Du schaust Dir die Exports dieser DLL mit meinem PE-Viewer an.


Nun gibt es bei Deinem Beispiel noch einen kleinen Trick.
Für CreateWindow() verwendest Du den Titel "edit", was eine statische
Zeichenkette ist, die in der .EXE in die Sektion mit initialisierten
Daten kommt.
Wenn Du keine inittialisierten Daten verwendest (static, "chararray", ...),
dann kann man sich diese Sektion (".rdata") sparen. Somit wird Dein
Beispiel nochmals um 0,5k kleiner - ist also dann 2,5k.

Dazu mußt Du die statische Zeichenkette ersetzen:

Code: Alles auswählen

char title[] = { 'e','d','i','t',0 };
HDC hDC = GetDC( CreateWindow( title, 0, ....
Du kannst es auch mal mit einem anderen C-Compiler probieren,
beispielsweise LCCwin32, PellesC oder andere.
Ich habe früher schon größere OpenGL-Beispiele in 1,5k oder 2k
untergebracht, und sogar GUI-Programme mit C++ (mit eigenem
OOP-Klassensystem) geschrieben, die dann mit 7-9k auskamen.
Das Prinzip (Standardbibliothek vom Linken ausschließen
und neuen Einsprungpunkt setzen) ist dabei eigentlich immer das gleiche.

Mit C ist das, wie oben aufgezeigt, ziemlich einfach. Wenn man mit
C++ eigene Klassen schreibt, dann muß man noch etwas mehr
beachten. So muß man dann z.B. die Operatoren "new" und "delete"
in seinen Klassen selbst implementieren, wenn man die Standard-
bibliothek nicht nutzen möchte.


Ich hoffe Dir hiermit ein wenig geholfen zu haben! Happy Coding... :)
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Hallo,

Danke erstmal für die Antwort. ;)
Danilo hat geschrieben:
DarkDragon hat geschrieben:Danke für den Tipp :-) . Aber viele Leute behaupten man könne auch ohne "rumdoktorn" mit C++ unter 5 kB kommen.
Hallo DarkDragon,

das hat nichts mit der Sprache C++ zu tun, sondern eher mit dem
Prozess des Kompilierens mit einem bestimmten Compiler(-system).
In Deinem speziellen Fall betrifft es den Linker.

Davon abgesehen ist Dein gezeigter Code nur C, nicht C++.
Ist mir klar, nur nutze ich einen C++ Compiler, und keinen C Compiler. Außerdem war das nur ein Beispiel, welches ich nichtmal unter 6kb bekommen habe. Mein Schulprojekt ist C++. Da nutze ich leider std, also kann ich das schonmal nicht entlinken. Ich nehms auch nicht so genau, weil ziemlich jeder weiß was gemeint ist.
Danilo hat geschrieben:Ich habe mir jetzt extra mal wieder DevC++ installiert und komme
mit Deinem Code auf eine .EXE von 3kb.
DevC++ Version ist 4.9.9.2 (GCC 3.4.2, LD 2.15.91).

Dazu gibst Du unter "Projekt Optionen > Parameter > Linker"
folgendes ein:

Code: Alles auswählen

-lkernel32
-luser32
-lgdi32
-lopengl32

-s
-nostdlib
--entry _WinMain@16
Die ersten 4 Zeilen teilen dem Linker mit welche Import-Libraries
er verwenden soll. Die ersten 3 sind Standard-WinAPI, die letzte
für OpenGL.
Wenn Du später weitere Libs benutzt, mußt Du die dort hinzufügen,
z.B. "-lglu32", "-lglut32" usw.

Die Linker-Option "-s" nimmt unbenutze Symbole aus dem Ergebniss
heraus.
Damit kommst Du wohl auf ca. 6,5kb.
Danke, fürs installieren. "-s" kann man auch unter den Projektoptionen einstellen unter Optimierungen "... strip symbols ..." irgendwo. "-nostdlib" und "--entry _WinMain@16" kannte ich bisher noch nicht.
Danilo hat geschrieben:Die letzten 2 Optionen sind nun entscheidend:
"-nostdlib" teilt dem Linker mit keine Standard-(C/C++)-Bibliotheken
einzufügen. Da Du keine C-Befehle (malloc etc.) benutzt, sondern
nur reines WinAPI, ist das kein Problem.
Mit "--entry _WinMain@16" setzt Du nun den Einsprungspunkt in
Deinem Programm. Dieser ist standardmässig in der Standardbibliothek,
die wir aber vom Linken ausgeschlossen haben.

Wenn Du nun Standard-C-Funktionen verwenden möchtest, dann
wird es zu einem Fehler kommen, da wir die Standardbibliothek
ja nicht benutzen.

Code: Alles auswählen

int *x = (int*)malloc(100);
Hier wird ein Linkerfehler kommen, da die Funktion "malloc" nicht
eingebunden wird. Dafür gibt es verschiedene Workarounds.

In diesem Beispiel könntest Du Dir ein eigenes "malloc" schreiben,
welches dann WinAPI-Funktionen benutzt (Global-/LocalAlloc oder
über die Heap-Funktionen).
Oder Du bindest die DLL "CRTDLL.dll" ein, so wie das auch PureBasic
macht. Wie der Name schon sagt, ist das eine C-Runtime-DLL mit
den C-Funktionen in einer DLL. Diese DLL ist seit Win95 mit dabei,
also überall vorhanden (sonst könnte es PB ja auch nicht verwenden).

Mit anderen C-Funktionen (strlen, printf usw.) ist es genauso.
Entweder selbst schreiben oder aus CRTDLL importieren.
Welche Funktionen enthalten sind findest Du sicherlich im MSDN,
oder Du schaust Dir die Exports dieser DLL mit meinem PE-Viewer an.


Nun gibt es bei Deinem Beispiel noch einen kleinen Trick.
Für CreateWindow() verwendest Du den Titel "edit", was eine statische
Zeichenkette ist, die in der .EXE in die Sektion mit initialisierten
Daten kommt.
Wenn Du keine inittialisierten Daten verwendest (static, "chararray", ...),
dann kann man sich diese Sektion (".rdata") sparen. Somit wird Dein
Beispiel nochmals um 0,5k kleiner - ist also dann 2,5k.

Dazu mußt Du die statische Zeichenkette ersetzen:

Code: Alles auswählen

char title[] = { 'e','d','i','t',0 };
HDC hDC = GetDC( CreateWindow( title, 0, ....
Du kannst es auch mal mit einem anderen C-Compiler probieren,
beispielsweise LCCwin32, PellesC oder andere.
Ich habe früher schon größere OpenGL-Beispiele in 1,5k oder 2k
untergebracht, und sogar GUI-Programme mit C++ (mit eigenem
OOP-Klassensystem) geschrieben, die dann mit 7-9k auskamen.
Das Prinzip (Standardbibliothek vom Linken ausschließen
und neuen Einsprungpunkt setzen) ist dabei eigentlich immer das gleiche.

Mit C ist das, wie oben aufgezeigt, ziemlich einfach. Wenn man mit
C++ eigene Klassen schreibt, dann muß man noch etwas mehr
beachten. So muß man dann z.B. die Operatoren "new" und "delete"
in seinen Klassen selbst implementieren, wenn man die Standard-
bibliothek nicht nutzen möchte.


Ich hoffe Dir hiermit ein wenig geholfen zu haben! Happy Coding... :)
Ich werds gleich mal ausprobieren :) . Danke nochmals. Werd auch va!n darüber informieren.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

DarkDragon hat geschrieben:"-nostdlib" und "--entry _WinMain@16" kannte ich bisher noch nicht.
Diese Optionen können bei allen Compilern/Linkern unterschiedlich
sein. Geh am besten mal an die Console, dann kannst Du Dir alle
Optionen der Tools im Verzeichniss Bin\ auflisten lassen.

Code: Alles auswählen

ld  --help
gcc --help
Oder in Datei umleiten.

Code: Alles auswählen

ld  --help >> ld_options.txt
gcc --help >> gcc_options.txt
Sind ja etliche Tools dabei, die man brauchen kann. Zum Beispiel "ar"
um Objektdateien zu Bibliotheken zusammenzufassen.
Begib Dich auf Entdeckungsreise, wenn Du das alles noch nicht kennst... ;)
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Danilo hat geschrieben:
DarkDragon hat geschrieben:"-nostdlib" und "--entry _WinMain@16" kannte ich bisher noch nicht.
Diese Optionen können bei allen Compilern/Linkern unterschiedlich
sein. Geh am besten mal an die Console, dann kannst Du Dir alle
Optionen der Tools im Verzeichniss Bin\ auflisten lassen.

Code: Alles auswählen

ld  --help
gcc --help
Oder in Datei umleiten.

Code: Alles auswählen

ld  --help >> ld_options.txt
gcc --help >> gcc_options.txt
Sind ja etliche Tools dabei, die man brauchen kann. Zum Beispiel "ar"
um Objektdateien zu Bibliotheken zusammenzufassen.
Begib Dich auf Entdeckungsreise, wenn Du das alles noch nicht kennst... ;)
"ar" ist mir auch bekannt (als erster Tailbite für Linux Programmierer muss man das ja kennen ;-) ). :-) Aber natürlich werde ich mal schauen was es da sonst noch gibt ;-) .
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Antworten