برنامج "Hello World" الخاص بـGC C++ -> يبلغ حجم ملف .exe 500 كيلو بايت عند تجميعه على نظام التشغيل Windows.كيف يمكنني تقليل حجمها؟

StackOverflow https://stackoverflow.com/questions/1042773

سؤال

لقد بدأت مؤخرًا في تعلم لغة C++ - وأنا أستخدمها nuwen's إصدار MingW على نظام التشغيل Windows، باستخدام NetBeans باعتباره IDE (لدي أيضًا إصدار MSDN AA من MSVC 2008، على الرغم من أنني لا أستخدمه كثيرًا).

عند تجميع هذا البرنامج البسيط:

#include <iostream>
using namespace std;

int dog, cat, bird, fish;

void f(int pet) {
  cout << "pet id number: " << pet << endl;
}

int main() {
  int i, j, k;
  cout << "f(): " << (long)&f << endl;
  cout << "dog: " << (long)&dog << endl;
  cout << "cat: " << (long)&cat << endl;
  cout << "bird: " << (long)&bird << endl;
  cout << "fish: " << (long)&fish << endl;
  cout << "i: " << (long)&i << endl;
  cout << "j: " << (long)&j << endl;
  cout << "k: " << (long)&k << endl;
} ///:~

كان الملف القابل للتنفيذ الخاص بي يبلغ حجمه حوالي 1 ميغابايت.عندما قمت بتغيير تكوين المشروع من تصحيح ل يطلق, ، تم استخدام علامات -O1 -Os (تجريد رموز التصحيح على طول الطريق)، وتم تقليل الحجم الثنائي من 1 ميجا بايت إلى 544 كيلو بايت.

أنا لست "مهووسًا بالحجم"، لكنني أتساءل فقط - هل هناك أي طريقة يمكنني من خلالها تقليل حجم .exe أكثر من ذلك؟أعتقد فقط أن 544 كيلو بايت يعد كثيرًا جدًا بالنسبة لمثل هذا التطبيق البسيط).

هل كانت مفيدة؟

المحلول

و

#include <iostream>

ويسبب الكثير من المكتبة القياسية لتكون مرتبطة في، على الأقل مع g ++. إذا كنت حقا تشعر بالقلق إزاء حجم قابل للتنفيذ، حاول استبدال جميع الاستخدامات أمام iostreams مع printf أو ما شابه ذلك. وهذا عادة ما تعطيك أصغر وأسرع للتنفيذ (حصلت لك إلى حوالي 6K) على حساب الراحة ونوع السلامة.

نصائح أخرى

المشكلة هنا لا تتعلق بالمكتبة بقدر ما تتعلق بالطريقة التي يتم بها
المكتبة مرتبطة.ممنوح، com.iostream هي مكتبة ضخمة إلى حد ما ولكني لا أفعل ذلك
أعتقد أنه يمكن أن يكون ضخمًا جدًا بحيث يتسبب في قيام البرنامج بإنشاء ملف قابل للتنفيذ
900KB أكبر من تلك المماثلة التي تستخدم C المهام.الشخص الذي يقع عليه اللوم
ليس iostream لكن gcc.بدقة اكثر، static linking هو إلقاء اللوم.

كيف تفسر هذه النتائج (مع برنامجك):

g++ test.cpp -o test.exe              SIZE: 935KB
gcc test.cpp -o test.exe -lstdc++     SIZE: 64.3KB

يتم إنشاء أحجام مختلفة من الملفات التنفيذية بنفس الطريقة تمامًا
بناء الخيارات.

الجواب يكمن في الطريق مجلس التعاون الخليجي يربط ملفات الكائن.
عند مقارنة مخرجات هذين الأمرين:

g++ -v test.cpp -o test.exe // c++ program using stream functions  
gcc -v test.c -o test.exe   // c program that using printf  

ستكتشف أن الأماكن الوحيدة التي تختلف فيها (بصرف النظر عن المسارات المؤدية إلى
ملفات الكائنات المؤقتة) موجودة في الخيارات المستخدمة:

   C++(iostream) | C(stdio)
-------------------------------
-Bstatic         |  (Not There)
-lstdc++         |  (Not There)
-Bdynamic        |  (Not There)
-lmingw32        | -lmingw32 
-lgcc            | -lgcc 
-lmoldname       | -lmoldname 
-lmingwex        | -lmingwex 
-lmsvcrt         | -lmsvcrt 
-ladvapi32       | -ladvapi32 
-lshell32        | -lshell32 
-luser32         | -luser32 
-lkernel32       | -lkernel32 
-lmingw32        | -lmingw32 
-lgcc            | -lgcc 
-lmoldname       | -lmoldname 
-lmingwex        | -lmingwex 
-lmsvcrt         | -lmsvcrt 

لقد حصلت على الجاني الخاص بك هناك في الأعلى. -Bstatic هو الخيار الذي يأتي
بالضبط بعد ملف الكائن الذي قد يبدو كالتالي:

"AppData\\Local\\Temp\\ccMUlPac.o" -Bstatic -lstdc++ -Bdynamic ....

إذا تلاعبت بالخيارات وقمت بإزالة المكتبات "غير الضرورية"،
يمكنك تقليل حجم الملف القابل للتنفيذ من 934KB ل 4.5KB الأعلى
في حالتي.فهمت ذلك 4.5KB باستخدام -Bdynamic, ، ال -O علَم
والمكتبات الأكثر أهمية التي لا يمكن لتطبيقك العيش بدونها، على سبيل المثال
-lmingw32, -lmsvcrt, -lkernel32.سوف تحصل على 25 كيلو بايت قابلة للتنفيذ عند ذلك
نقطة.تجريدها إلى 10 كيلو بايت و UPX إلى حولها 4.5KB-5.5KB.

إليك ملف Makefile للعب به، من أجل الركلات:

## This makefile contains all the options GCC passes to the linker
## when you compile like this: gcc test.cpp -o test.exe
CC=gcc

## NOTE: You can only use OPTIMAL_FLAGS with the -Bdynamic option. You'll get a
## screenfull of errors if you try something like this: make smallest type=static
OPTIMAL_FLAGS=-lmingw32 -lmsvcrt -lkernel32

DEFAULT_FLAGS=$(OPTIMAL_FLAGS) \
-lmingw32 \
-lgcc \
-lmoldname \
-lmingwex \
-lmsvcrt \
-ladvapi32 \
-lshell32 \
-luser32 \
-lkernel32 \
-lmingw32 \
-lgcc  \
-lmoldname \
-lmingwex \
-lmsvcrt


LIBRARY_PATH=\
-LC:\MinGW32\lib\gcc\mingw32\4.7.1 \
-LC:\mingw32\lib\gcc \
-LC:\mingw32\lib\mingw32\lib \
-LC:\mingw32\lib\

OBJECT_FILES=\
C:\MinGW32\lib\crt2.o \
C:\MinGW32\lib\gcc\mingw32\4.7.1\crtbegin.o

COLLECT2=C:\MinGW32\libexec\gcc\mingw32\4.7.1\collect2.exe

normal:
    $(CC) -c test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(DEFAULT_FLAGS) $(LIBRARY_PATH) -o test.exe

optimized:
    $(CC) -c -O test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(DEFAULT_FLAGS) $(LIBRARY_PATH) -o test.exe

smallest:
    $(CC) -c -O test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(OPTIMAL_FLAGS) $(LIBRARY_PATH) -o test.exe

ultimate:
    $(CC) -c -O test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(OPTIMAL_FLAGS) $(LIBRARY_PATH) -o test.exe
    strip test.exe
    upx test.exe

CLEAN:
    del *.exe *.o

النتائج (YMMV):

// Not stripped or compressed in any way
make normal    type=static     SIZE: 934KB
make normal    type=dynamic    SIZE: 64.0KB

make optimized type=dynamic    SIZE: 30.5KB
make optimized type=static     SIZE: 934KB

make smallest  type=static     (Linker Errors due to left out libraries)
make smallest  type=dynamic    SIZE: 25.6KB 

// Stripped and UPXed
make ultimate type=dynamic    (UPXed from 9728 bytes to 5120 bytes - 52.63%)
make ultimate type=static     (Linker Errors due to left out libraries)

سبب محتمل لإدراج -Bstatic في خيارات البناء الافتراضية
هو لأداء أفضل.حاولت البناء astyle مع -Bdynamic وحصلت
انخفاض السرعة بمقدار ثانية واحدة في المتوسط، على الرغم من أن التطبيق كان جيدًا
أصغر من الأصل (400 كيلو بايت مقابل 93 كيلو بايت عند UPXed).

ولست متأكدا كم استخدامه سيكون لكم، ولكن <لأ href = "http://web.archive.org/web/20111214171623/http://www.phreedom.org/solar/code/tinype/ "يختلط =" noreferrer نوفولو "> شخصا ما قد فعلت الكثير من العمل على تخفيض حجم ويندوز إكس بسيط .

وكانت قادرة على خلق إكس بسيطة من شأنها تنفيذ على النسخة الحديثة من نظام التشغيل Windows في 133 بايت، وذلك باستخدام بعض الأساليب القاسية جدا.

هل يمكن استخدام -s، التي أعتقد أنها بنيت في مينغو كذلك. تطبيق مرحبا بسيط العالم المترجمة باستخدام ز ++ 3.4.4 على سيغوين إنتاج قابل للتنفيذ الذي كان 476872 بايت، وتجميع مرة أخرى مع -s (شرائط البيانات غير الضرورية)، وانخفاض نفسه للتنفيذ إلى 276480 بايت.

ونفس الطلب العالمي مرحبا في سيغوين باستخدام ز ++ 4.3.2 إنتاج قابل للتنفيذ من 16495 بايت، وذلك باستخدام شريط تخفيض حجم 4608 بايت. بقدر ما أستطيع أن أرى، وربما الأفضل استخدام إصدار أحدث من ز ++.

ومينغو قد صدر للتو دول مجلس التعاون الخليجي 4.4.0، لذلك إذا كان حجم القابل للتنفيذ هو المهم ثم فما استقاموا لكم فاستقيموا النظر في استخدام ذلك. كما يشير -s من المحتمل أن تساعد قطاع الكثير من المعلومات التصحيح للكم، وهذا هو الموصى بها إلا إذا كانت للاستخدام الإنتاج.

وتحصل على C ++ مكتبة القياسية، وغيرها من الاشياء واعتقد، مرتبطة بشكل ثابت في مينغو كما يوجد تنفيذه الخاصة من هذه المكتبات.

لا تقلق كثيرا حول هذا الموضوع، عند تقديم برنامج أكثر تعقيدا، فإن حجم لا تنمو وفقا لذلك.

والأساس، وليس هناك في الواقع أي شيء يمكنك القيام به للحد من تلك إكس الحجم مع توزيع قاعدة مينغو. 550kb حوالي صغيرة مثل يمكنك الحصول عليه، لأن مينغو ودول مجلس التعاون الخليجي / ز ++ بشكل عام سيئة في تجريد وظائف غير المستخدمة. حول 530kb من ذلك هو من المكتبة msvcrt.a.

إذا كنت تريد حقا للوصول الى ذلك، قد تكون قادرا على إعادة بناء مكتبة msvcrt.a مع المقاطع -ffunction -fdata المقاطع خيارات المترجم، ومن ثم استخدام -Wl، - أقسام القيادة العامة خيارات رابط عندما ربط التطبيق الخاص بك، وهذا ينبغي أن يكون قادرا على تجريد الكثير من الاشياء التي من هناك. ولكن إذا كنت مجرد تعلم C ++، وإعادة بناء هذه المكتبة قد يكون قليلا متقدمة.

وأو هل يمكن أن مجرد استخدام MSVC، وهو أمر عظيم في تجريد وظائف غير المستخدمة. نفس الشيء من التعليمات البرمجية المترجمة مع MSVC تنتج إكس 10KB.

وكذلك عند استخدام المكتبة القياسية C ++، إكس يمكن الحصول كبير حقا بسرعة. إذا بعد تجريد الرموز التصحيح، كنت لا تزال تريد تقليل حجم البرنامج الخاص بك، يمكنك استخدام باكر مثل UPX . ولكن، حذر من أن يكون، وبعض الفيروسات خنق على إكس محملة UPX عن بعض الفيروسات استخدامه منذ فترة طويلة.

هل يمكن تشغيل دائما UPX على إكس بك بعد أن كنت قد إنشائه.

إذا كنت تستخدم "نانومتر" المنفعة أو بعض البرامج الأخرى التي تظهر ماذا يكون في إكس الخاص بك، سترى أنها تحتوي على طن من الفئات التي شخص <م> قد تريد استخدامه، ولكن ان كنت لا.

وأنا تكرار الاختبار باستخدام سيغوين وز ++. التعليمات البرمجية المترجمة إلى 480K مع -O2. تشغيل <ط> شريط على تنفيذ يتحول إلى 280K.

في عام، على الرغم من وأظن مشكلتك هو استخدام رأس . يؤدي هذا مكتبة كبيرة إلى حد ما تكون مرتبطة في. لاحظ أيضا أن cout << x يفعل أكثر بكثير من الطباعة فقط. هناك غات وتيارات وجميع أنواع الأشياء تحت غطاء محرك السيارة.

إذا ومع ذلك، وجود حجم صغير قابل للتنفيذ هو الهدف الحقيقي، ذات المهام الحرجة، ثم تجنب ذلك واستخدام printf أو يضع. إذا لم تكن كذلك، ثم أود أن أقول دفع تكاليف لمرة واحدة iostream وينبغي القيام به معها.

إذا كنت تحتاج التنفيذية صغيرة، وصغيرة C تجميع 1536 بايت قابل للتنفيذ لprintf ( "أهلا بالعالم!") TinyC هو C فقط، وليس C ++ وكما هو معروف لتجميع أسرع وأبطأ إعطاء التنفيذية من دول مجلس التعاون الخليجي.

وتعديل: لقد حاولت مجرد cout < "مرحبا العالم!" في DevC ++ (حزم مينغو 4.8 وIDE) وحصلت على 4،5 MB قابل للتنفيذ !!

وكيف يمكن أن يكون المجمعين أخرى مثل msvc8 أو حتى مترجم أجل مثل بورلاند ج ++ 5.5.1 قادرون على انتاج التنفيذية صغيرة جدا ولكنها دول مجلس التعاون الخليجي مينغو ليست قادرة على؟

ولقد فعلت ذلك لتجميع سريع ل'مرحبا العالم لكل من يلي من toolsets ولاحظ حجم قابل للتنفيذ المترجمة. يرجى ملاحظة أنه في كل هذه الحالات يرتبط مكتبة وقت التشغيل بشكل ثابت وجميع التصحيح تم تجريد الرموز:

compiler toolchain            exe size                   exe size
                              (w/iostream header)        (w/cstdio printf)
-------------------------------------------------------------------------
Borland C++ 5.5.1             110kbyte                    52kbyte
MSVC 2008 express             102kbyte                    55kbyte
MinGW- GCC 3.4.5              277kbyte                    <10kbyte
MinGW- GCC 4.4.1              468kbyte                    <10kbyte

ما هو المثير للاهتمام هو إصدار أحدث من دول مجلس التعاون الخليجي 4.4.1 ينتج للتنفيذ حتى أكبر من gcc3.4.5، وربما يرجع ذلك إلى إصدار مختلف من libstdc ++.

وحتى لا يكون هناك حقا أي وسيلة لإزالة رمز قتيلا خلال مرحلة ربط لمينغو؟

ينبع الجزء الأكبر من الحجم من استخدام مكتبات وقت التشغيل واسعة النطاق إلى حد ما.لذلك، في الحياة الواقعية، فإنك تقوم في الواقع بربط جزء كبير جدًا من "الرمز الميت" إذا كان لديك مثل هذا التطبيق البسيط.

بقدر ما أعرف لا توجد علامات رابط لتخطي الأجزاء غير المستخدمة من المكتبة المرتبطة.

هناك طريقتان أعرفهما لتزييف تطبيق أصغر:

  1. استخدم الارتباط الديناميكي.ثم يشير تطبيقك إلى المكتبة المحملة ديناميكيًا.لا تزال بحاجة إلى الحجم الكامل (في الواقع أكثر) ولكن لديك ملفًا تنفيذيًا أصغر بكثير.
  2. استخدم ضغط قابل للتنفيذ نظام.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top