На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела FAQ в группе разделов С++.
1. Раздел FAQ предназначен для публикации готовых статей.
2. Здесь нельзя задавать вопросы, для этого существуют соответствующие разделы:
Чистый С++
Visual C++ / MFC / WTL / WinApi
Borland C++ Builder
COM / DCOM / ActiveX / ATL
Сопутствующие вопросы
3. Внимание, все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут видны остальным участникам только после одобрения модератора.
Модераторы: B.V., Qraizer
  
> Минимизация размера программ , зачем? для гармонии и ДАО
    Очень часто у программистов (обычно начинающих, а иногда и не только) возникают вопросы по поводу размера получающихся программ, особенно программ типа "Hello World!" :), мол, почему моя программа получается 36 кб(VC++) или 300-400 кб (BCB,Delphi), хотя почти ничего при этом не делает. В этой теме я хочу по возможности ответить на подобные вопросы, подсказать, как быстро урезать программу, как правильно программировать, чтобы программа получилась на порядок меньше.
    Сам я маниак, люблю компактные программы (надо сразу оговориться, что сам я ковыряюсь только под VC++, под Delphi буду выкладывать только статьи и примеры).
    (Те, кто считает, что размер программы в настоящее время не играет никакой роли могут не тратить время и не читать далее. Так же не надо озвучивать и своё мнение по этому поводу.)
    ----------------------------------------------------
    Итак, вот типичный вопрос (с этого же форума):
    Цитата

    Написал простенький код на VC:
    ExpandedWrap disabled
      #include <stdio.h>
       
      int main(int argc, char *argv[ ])
      {
          printf("%s",argv[1]);
          return 0;
      }

    После компиляции .obj файл занимает 2 кб, но линкер преобразует ео в огромный 36кб exe по видимому включая в него ненужные библиотеки. Помогите разобраться в этом. Какие опции линковщика нужно применить чтобы сделать программу нормального размера?


    что можно сделать в таком случае, не вдаваясь особо в технические детали?
    Можно правильно настроить свой проект:
    для начала в опциях линкера -> Optimization -> References надо выбрать "Eliminate Unreferenced Data (/OPT:REF)",
    там же Enable COMDAT folding установи Remove Redundant COMDATs (/OPT:ICF),
    Optimize for Win98 выбрать NO
    в результате - код уменьшится до 26.5 кб без каких либо потерь функциональности.
    Далее, можно в начало файла вставить такие строчки
    ExpandedWrap disabled
      #pragma comment(linker, "/MERGE:.rdata=.text")
      //#pragma comment(linker, "/MERGE:.data=.text")
      #pragma comment(linker, "/SECTION:.text,EWRX")

    из первых двух строк надо оставить незакомменченной только одну любую (иногда обе) - выиграешь ещё полкилобайта (мелочь, но приятно).

    Результат - 26 кб - БЕЗ ПОТЕРЬ ФУНКЦИОНАЛЬНОСТИ.
    Причем твоя программа может переноситься с компа на комп и не будет требовать никаких библиотек, так как ей нужен для работы только kernel32.dll.

    Теперь можно сделать следующее - заходим в опции C/C++ -> Code Generation.
    Смотрим на строку Runtime Library. Скорее всего там стоит "Single-threaded (/ML)", что означает, что к программе прилинковывается код инициализации библиотеки времени выполнения (так называемый С runtime, CRT), который в нашей похудевшей до 26 кб программе составляет около 23 кб.
    Убедиться в этом можно выбрав в этой опции "Multi-threaded DLL (/MD)".
    Компилим и получаем .EXE файл размером 2.5 кб. Вуаля.

    Одно замечание - теперь твоей программе для работы необходима библиотека msvcr70.dll (это в студии 7.0), при компиляции в другой студии может требоваться немного другая, типа msvcr71.dll (для студии 7.1).
    То есть если ты вдруг скопируешь программу на компьютер, где нет такой библиотеки, то она работать не будет. (Но, по-моему,
    в windows нет проблем с этими библиотекми.)
    функциональность в этом случае не страдает - можно пользоваться стандартными функциями С как обычно.

    Ну и в конце концов можно радикально отказаться от этого кода инициализации, в каком бы он виде не был - dll или статически (навсегда) прилинкованный к программе.
    Но тогда ты лишаешься возможности использовать как обычно функции CRT, например стандартную strcpy() или ту же printf(). Можно использовать только WinAPI и писать/использовать свои варианты необходимых функций, которых нет в winapi. Например вместо strcpy() отлично работает lstrcpy(), и так с несколькими строковыми функциями. А например оператор NEW ты использовать не сможешь, как и malloc() и т.п., надо использовать HeapAlloc(), GlobalAlloc() и пр.

    Выигрыш только в размере за счёт потери удобства программирования. Так что это имеет смысл только для крошечных программ и утилит, либо если ты хочешь прослыть эстетом.
    Например твоя программа несколько видоизмененная будет весить 1 кб и не требовать никаких библиотек.
    ExpandedWrap disabled
      #pragma comment(linker, "/MERGE:.rdata=.text")
      #pragma comment(linker, "/SECTION:.text,EWRX")
      #include <Windows.h>
      int main(/*int argc, char *argv[ ]*/)
      {
          //printf("%s",argv[1]);
          LPTSTR cmd = GetCommandLine();
          DWORD t;
          WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), cmd, lstrlen(cmd), &t, NULL);
          return 0;
      }

    Правда это не совсем та программа, поскольку она выводит полностью комстроку, так как возможность использовать int argc, char *argv[] потеряна и необходимо парсить комстроку как-то по другому. Варианты есть, но я не буду здесь распространяться, это уже другой вопрос.
    Размер программы теперь - 1 кб. Ну или даже 718 байт.

    Как сотворить сие злодеяние?
    в опциях линкера Advanced -> Entry Point установить "main" ну и чуть подправить код.

    всё вышесказанное в равной степени относится к неконсольным windows-программам
    Сообщение отредактировано: vito333 -

    Прикреплённый файлПрикреплённый файлMicroConsole.zip (0.42 Кбайт, скачиваний: 277)
      А дальше? :blink:
        то есть если быть точным, то при компиляции получился файл размером 1 кб, но когда счёт совсем на байты идёт, я обычно использую yoda's PERealigner 2.0 (y0da.cjb.net - там, кстати, ещё куча полезных программ и исходников есть).
        Он то и почикал без всякой компрессии полученный 1 кб, превратив его в 718 байт.

        Из множества разных pe-optimizer-ов он оказался самым стабильным и эффективным.
        Прикреплённый файлПрикреплённый файлPeRealigner2.zip (5.5 Кбайт, скачиваний: 314)
          в качестве примера микро-программ выкладываю три проекта (скорее проектика :)), наглядно демонстрирующих радикальный отказ от библиотеки CRT.
          Это EmptyBin - при запуске программа очищает "Корзину" и тут же выходит;
          MicroHelloWorld - программа выводит окно сообщения с самым популярным программистским сообщением;
          MicroGDI - программа-пример из книги Фэнь Юаня.

          Ну и что, скажете вы, размеры крошечные, а толку? ничего полезного эти программы не делают.
          Тогда пойдём и глянем тут:
          NanoTime v.091
          обрезание CRT позволило уменьшить программу почти в три раза, а программа не совсем уж бесполезная.
          Сообщение отредактировано: vito333 -

          Прикреплённый файлПрикреплённый файл_Micro_Bunch.zip (27.19 Кбайт, скачиваний: 284)
            теперь самое время утолить жажду познания тех, кто хочет копнуть глубже и выяснить, откуда ноги (уши, хвосты) растут :)

            Нет, сам я не осилю, есть настоящие спецы.
            самая лучшая статья по оптимизации для пишущих на VC++ 6,7 (да и 8 наверное):
            http://www.rsdn.ru/article/cpp/crt.xml
            или она же:
            http://www.rsdn.ru/article/?51
            в этой же статье описано, как и почему возникает популярное
            Цитата
            LIBCMT.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

            ---------------------------
            приложу её на всякий случай
            Прикреплённый файлПрикреплённый файлCRTanatomy.zip (47.37 Кбайт, скачиваний: 256)
              всё это хорошо, скажете вы, но это же каменный век! как кодить на C++ без new? без delete? а как же классы?
              трудно, но возможно. Раз не хочется цеплять к маленькой супер-программе тяжелый хвост CRT, надо прицепить маленький хвостик, какую нибудь другую CRT!
              Давным давно дядька Matt Pietrek поработал над этим вопросом и даже выдал на гора результат - статью и библиотеку
              "Reduce EXE and DLL Size with LIBCTINY.LIB"
              http://msdn.microsoft.com/msdnmag/issues/01/01/hood/default.aspx
              с исходниками

              конечно, она (библиотека) несколько устарела, не поддерживает юникод, к тому же она таки весьма малофункциональна, но new и delete она вам обеспечит, так что уже можно писать небольшую утилитку с её помощью. Всё что надо сделать - в свойствах проекта Linker -> Additional Dependencies - LIBCTINY.LIB

              Прикладываю пример проекта (для студии 7.1, для 7.0 переименуйте файлы с расширением .old) с использованием этой библиотеки. В примере нормальная работа с классами, создаётся окно, всё чин по чину.
              Прикреплённый файлПрикреплённый файлwinnie.zip (14.53 Кбайт, скачиваний: 262)
                вот кстати в тему
                Написание экстра-маленьких Win32 приложений на С++ от 1 КБ используя лишь API, на примере программы Windows Hider
                http://www.uinc.ru/articles/28/index.shtml
                уж не помню, чего я там подкрутил :), но получилось ещё поменьше - мой проект в архиве тоже.

                там же на странице ссылка на исходник примера микро-dll - да,да, с ними дело обстоит точно так же, как и с ЕХЕ.
                Сообщение отредактировано: vito333 -

                Прикреплённый файлПрикреплённый файлwinhider.zip (29.84 Кбайт, скачиваний: 254)
                  возвращаясь к теме - Как же без лишних ухищрений ваять маленькие проги, при этом в стиле C++ и не особо заморачиваясь? LIBCTINY.LIB старовата и скудновата, самому всё переписывать все функции CRT?

                  ещё один известный дядька Joergen Ibsen / Jibz для любителей мелочи написал неплохую библиотеку, которая очень хорошо перекрывает стандартную CRT, особенно для неюникодовых проектов.

                  Называется она WCRT - Win32API CRT

                  Version 1.12
                  Copyright (c) 2003-2004 by Joergen Ibsen / Jibz
                  All Rights Reserved
                  http://www.ibsensoftware.com/

                  используется как в примере выше, единственное - возможно придётся отключить стандартные библиотеки.

                  Вообще-то с библиотекой идёт отличная документация.
                  Сообщение отредактировано: vito333 -

                  Прикреплённый файлПрикреплённый файлWCRT_1.12.zip (88.58 Кбайт, скачиваний: 431)
                    Цитата vito333 @
                    для начала в опциях линкера -> Optimization -> References надо выбрать "Eliminate Unreferenced Data (/OPT:REF)",
                    там же Enable COMDAT folding установи Remove Redundant COMDATs (/OPT:ICF),
                    По моему, в статье стоило бы объяснить, что эти опции значат.

                    Цитата vito333 @
                    Одно замечание - теперь твоей программе для работы необходима библиотека msvcr70.dll (это в студии 7.0), при компиляции в другой студии может требоваться немного другая, типа msvcr71.dll (для студии 7.1).
                    То есть если ты вдруг скопируешь программу на компьютер, где нет такой библиотеки, то она работать не будет. (Но, по-моему,
                    в windows нет проблем с этими библиотекми.)
                    Версия 7.* CRT и MFC поставляется с виндами, только начиная с ХР, по моему. В остальных виндах нет проблем с версией CRT, которая поставлялась с шестой студией.

                    Стоило бы поправить кучу орфографических ошибок :lol: , про запятые я вообще молчу ;)
                    Цитата vito333 @
                    А напрмер оператор NEW ты использовать не сможешь,

                    Цитата vito333 @
                    Напрмер твоя программа несколько видоизмененная

                    Цитата vito333 @
                    там же на транице ссылка на

                    Цитата vito333 @
                    ухищрений ваять мленькие проги, при


                    Теперь об общем, стиль какой-то взбаломошный - нет единства. Надо бы объединить твои дополнительные сообщения в одно. Ну это, если ты на статью претендовать хочешь... А так, если поступать по опыту дельфей или БД, которые просто переносят ответы из форума в ФАК, то сгодится, конечно <_< Хотя, мне не нравится идея топика ФАКа, который вобщем-то предоставляет из себя только дополненную комментариями ссылку на статьи РСДНа :(
                      Leprecon
                      мне, в общем, всё равно, статья или не статья, главное суть, а именно - ответы на частые вопросы. Ошибки - поправлю, неясное - дополнительно разъясню. И опираюсь не только на статьи с рсдн, но и на собственный опыт в этом деле. Далее выложу и советы(статьи) по Delphi, чтобы люди и на нём могли красиво писать.
                      Меня больше привлёк тот момент, что можно приаттачить статьи и файлы, потому как если с рсдн статья никуда не денется, то статьи по Delphi всё больше по личным страницам разбросаны, так что есть риск их потерять.
                      Ну а стиль - действительно не статейный, так как именно статью писать не планировал.

                      "Достаточно, чтобы слова выражали смысл"(с)
                        теперь немного о Delphi
                        Цитата

                        Выжимаем из Delphi все возможное

                        Ты пишешь на дельфях и чувствуешь себя аутсайдером? Тебе нечем ответить в бесконечных hollywar'ах? Теперь ты точно будешь знать: дельфи стоит того, чтобы его любить. И не только из-за простоты этого языка. Очень маленькие и очень быстрые программы на дельфи - это возможно! Ты расскажешь об этом всем сомневающимся. И с мнением, что дельфи - язык для ламеров, будет покончено!

                        Многие системные программисты привыкли считать Delphi полным отстоем. Свое мнение они аргументируют тем, что компилятор генерирует слишком медленный и большой код, а средний размер пустой формы с кнопкой - 400 килобайт. Впрочем, иногда никаких аргументов и вовсе не приводится. Когда на форумах сталкиваются поклонники С++ и Delphi, первые обычно кричат о супернавороченном синтаксисе и потрясающих возможностях ООП, при этом утверждая, что в системном программировании все это необходимо, а вторые - о возможностях того же ООП на дельфи, которых нет в С++, и о том, что на этом языке писать проще. Из слов и тех, и других можно заключить, что обе стороны ни про Delphi, ни про C++ ничего толком не знают, и все это - пустая ламерская болтовня.

                        Эта статья посвящена приемам системного программирования на Delphi. Она написана для тех, кто любит этот язык, хочет добиться максимальной эффективности кода и не боится вложить в свое дело определенный труд. Я покажу, как делать на дельфи то, что многие считают невозможным. Тем, кто занимается кодингом на С++, не составит труда найти целую кучу статей по оптимизации. Если же ты пишешь на Delphi, ты не найдешь на эту тему ничего хорошего. Видимо, все считают, что никакой оптимизации здесь не нужно. Может быть, тебя устраивает 400-килобайтная пустая форма с кнопкой? А, ты думаешь, что это неизбежное зло, и уже давно с ним смирился? Что ж, придется немного расстроить твои нервы и развеять священные заблуждения.

                        Прикреплённый файлПрикреплённый файлDelphi_all_power.zip (8.79 Кбайт, скачиваний: 317)
                          принципы оптимизации размера программ для Delhpi и Borland C++ весьма похожи, но вот статья и пример специально для BCB

                          Цитата

                          Сборка очень маленьких программ в Borland C++ Builder (06-май-2003)

                          Здесь описан порядок сборки программ или DLL не нуждающихся ни в VCL ни в RTL.

                          Прикреплённый файлПрикреплённый файлLittleTask.zip (10.41 Кбайт, скачиваний: 267)
                            Цитата vito333 @
                            теперь немного о Delphi
                            Цитата

                            Выжимаем из Delphi все возможное

                            А не пойти ли Вам из C++-фака куда-нибудь подальше, например в Delphi и иже с ними? >:(
                            Сообщение отредактировано: Hryak -
                              vito333, ты давай определяйся, как будешь выделять отсюда про Delphi и куда это переносить.
                                хм, и точно, чего-то я протупил. Не буду про Delphi ни писать, ни переносить.
                                  Т.е. ты предлагаешь модераторам удалить/переместить на свое усмотрение? Я и так замучался нажимать кнопку "Разрешить" :)
                                    trainer
                                    я предлагаю оставить в топике один маленький постец относительно Delphi (уберу остальные), а в нём напишу что-то вроде "всё про минимизацию программ на Delphi - в аттаче", прицеплю архив, и пусть пост останется тут, так как про Delphi я не буду развивать тему где либо ещё, и если не будет тут - не будет нигде.
                                    Ок?

                                    и чего за "Разрешить" такое?
                                    Сообщение отредактировано: vito333 -
                                      Цитата vito333 @
                                      и чего за "Разрешить" такое?
                                      Любое сообщение или тема в этом разделе появляются на всеобщее обозрение только после того, как это разрешит модератор.
                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                      0 пользователей:


                                      Рейтинг@Mail.ru
                                      [ Script execution time: 0,0710 ]   [ 16 queries used ]   [ Generated: 25.04.24, 04:24 GMT ]