Большой Воронежский Форум
» Программирование>Вопрос по Visual C++ 2005
Pengvin 21:48 03.08.2006
Долго читал на форумах о прекрасной оптимизации в Visual Studio и какое это счастие там программировать. Сегодня сходил к другу 3 часа закачивал Visual Studio 2005 с голимого сервера. Скомпилировал следующий файлик
#include <windows.h>
void main()
{
MessageBox(0,"text","text",MB_OK);
}
И получил экзешник размером 48 Кб. Больше в проекте кроме main.cpp ничего нет даже ресурсов. Объясните лому как уменьшить размер проги в студии. Я конечно понимаю что оптимизацию из коробки мне не получить но хотелось бы что нибудь поменьше. Даже дельфи всеми преданный анафеме делает проги меньше. [Ответ]
Pengvin 21:57 03.08.2006
и еще вот сколько мне гов*а студия напихала в экзешник

Сообщение от :
extrn GetSystemTimeAsFileTime extrn GetCommandLineA extrn HeapFree extrn GetVersionExA extrn HeapAlloc extrn GetProcessHeap extrn GetProcAddress extrn GetModuleHandleA extrn ExitProcess extrn WriteFile extrn GetStdHandle extrn GetModuleFileNameA extrn UnhandledExceptionFilter extrn FreeEnvironmentStringsA extrn GetEnvironmentStrings extrn FreeEnvironmentStringsW extrn WideCharToMultiByte extrn GetLastError extrn GetEnvironmentStringsW extrn SetHandleCount extrn GetFileType extrn GetStartupInfoA extrn DeleteCriticalSection extrn TlsGetValue extrn TlsAlloc extrn TlsSetValue extrn TlsFree extrn InterlockedIncrement extrn SetLastError extrn GetCurrentThreadId extrn InterlockedDecrement extrn HeapDestroy extrn HeapCreate extrn VirtualFree extrn QueryPerformanceCounter extrn GetTickCount extrn GetCurrentProcessId extrn LeaveCriticalSection extrn EnterCriticalSection extrn TerminateProcess extrn GetCurrentProcess extrn SetUnhandledExceptionFilter extrn IsDebuggerPresent extrn LoadLibraryA extrn InitializeCriticalSection extrn Sleep extrn GetCPInfo extrn GetACP extrn GetOEMCP extrn VirtualAlloc extrn HeapReAlloc extrn RtlUnwind extrn HeapSize
extrn MultiByteToWideChar extrn GetLocaleInfoA extrn LCMapStringA extrn LCMapStringW extrn GetStringTypeA extrn GetStringTypeW

Как эту хрень убрать из экзешника? Желательно при компиляции а не потом напильником и стамеской [Ответ]
Pengvin 22:00 03.08.2006
пардон конечно не все функции но допустим WriteFile и другие функции сомнительной пользы для моей проги [Ответ]
VBA b0.3 09:39 04.08.2006
ты демку 64к задумал сделать, или 4к...
или просто за державу обидно ? [Ответ]
SteelViper 10:40 04.08.2006
в исходнике windows.h можно найти следующую информацию

/* If defined, the following flags inhibit definition
* of the indicated items.
*
* NOGDICAPMASKS - CC_*, LC_*, PC_*, CP_*, TC_*, RC_
* NOVIRTUALKEYCODES - VK_*
* NOWINMESSAGES - WM_*, EM_*, LB_*, CB_*
* NOWINSTYLES - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
* NOSYSMETRICS - SM_*
* NOMENUS - MF_*
* NOICONS - IDI_*
* NOKEYSTATES - MK_*
* NOSYSCOMMANDS - SC_*
* NORASTEROPS - Binary and Tertiary raster ops
* NOSHOWWINDOW - SW_*
* OEMRESOURCE - OEM Resource values
* NOATOM - Atom Manager routines
* NOCLIPBOARD - Clipboard routines
* NOCOLOR - Screen colors
* NOCTLMGR - Control and Dialog routines
* NODRAWTEXT - DrawText() and DT_*
* NOGDI - All GDI defines and routines
* NOKERNEL - All KERNEL defines and routines
* NOUSER - All USER defines and routines
* NONLS - All NLS defines and routines
* NOMB - MB_* and MessageBox()
* NOMEMMGR - GMEM_*, LMEM_*, GHND, LHND, associated routines
* NOMETAFILE - typedef METAFILEPICT
* NOMINMAX - Macros min(a,b) and max(a,b)
* NOMSG - typedef MSG and associated routines
* NOOPENFILE - OpenFile(), OemToAnsi, AnsiToOem, and OF_*
* NOSCROLL - SB_* and scrolling routines
* NOSERVICE - All Service Controller routines, SERVICE_ equates, etc.
* NOSOUND - Sound driver routines
* NOTEXTMETRIC - typedef TEXTMETRIC and associated routines
* NOWH - SetWindowsHook and WH_*
* NOWINOFFSETS - GWL_*, GCL_*, associated routines
* NOCOMM - COMM driver routines
* NOKANJI - Kanji support stuff.
* NOHELP - Help engine interface.
* NOPROFILER - Profiler interface.
* NODEFERWINDOWPOS - DeferWindowPos routines
* NOMCX - Modem Configuration Extensions
*/

так что напильник в руки и вперед [Ответ]
aerin 12:12 04.08.2006
Pengvin
Давненько я не брал в руки шашек!
сразу ремарка: VC 2005 сейчас под рукой нет, поэтому будем кивирять 2003
Но я далек от мысли, что в 2005 кардинально все по другому...
Итак поехали.
Пустой проект win32. Добавляем файл mini.cpp:

Сообщение от :
#include <windows.h>

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
MessageBox( NULL, "Hello from VC!", "Message", MB_OK | MB_ICONINFORMATION );

return 0;
}

Конфигурация Release. Все остальное по дефолту. Компиляем. Размер mini.exe = 22528 байт.(Кстати непонятно, как вам удалось получить 48к?)
Идем дальше. Смотрим командную строку линкера:

Сообщение от :
/OUT:"Release/mini.exe" /INCREMENTAL:NO /NOLOGO /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /MACHINE:X86 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

Как-то, не весело, хотя в тексте и присутствует /opt:ref...
Ясно, что раз зашел разговор о размере, то большая часть либ нам и завтра не понадобится вместе со стартап-кодом

Поехали. До свидания все дефолтные либы - /NODEFAULTLIB. mini.cpp принимает вид:

Сообщение от :
#include <windows.h>

void Start()
{
MessageBox( NULL, "Hello from VC!", "Message", MB_OK | MB_ICONINFORMATION );
}

Добавляется опция - /ENTRY:"Start". Компиляем - 2048байт.
Так сойдет или еще поковырять?
[Ответ]
zss_vrn 12:21 04.08.2006
aerin,
Респект [Ответ]
aerin 13:53 04.08.2006
zss_vrn
Было бы за что, смысла в этом не вижу... [Ответ]
Pengvin 20:50 04.08.2006
aerin, спасибо Сейчас все это попробуем я , остатками мозгов , понимаю что все это не в командной строке писать а прагмами в коде.
Так получилось 2560 байтов . Круто. [Ответ]
Pengvin 21:02 04.08.2006
вот мне тут люди еще подсказали вот такую хрень

Сообщение от :
#pragma comment(linker,"/MERGE:.rdata=.text")

Получилось как раз 2048 байт
Нет вы не подумайте что я придераюсь просто нехорошо когда в тривиальный хелло ворлд линкер набивает всякого другого барахла [Ответ]
aerin 01:41 05.08.2006
А какая разница, где писать, эффект-то одинаковый?
С объединением сегментов надо быть поаккуратнее, т.к. я думаю MessageBox-ом дело не ограничится [Ответ]
Pengvin 20:23 05.08.2006
aerin, конечно не кончится. Да и на смерженные сегменты warnings пошли Я просто недавно достал DirectX SDK и решил покодить трехмерные проги. Пришлось визуал студию ставить. Все мне рекомедовали 6 но я смог только 2005 достать. Теперь вот мучаюсь может мне стит 6 поискать?
Тут вот еще такая трабла.
линкер вот что пишет:

Сообщение от :
error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

Добавляю void main () он начинае опять всякую муть в экзешник тянуть. Правда я еще один cpp файлик в проект добавил Без него все норамльно пашет. Но не инклудами же весь код писать? [Ответ]
aerin 23:27 06.08.2006
Pengvin. При создании проекта ты сказал VC, что хочешь консольную софтину, вот студия и ищет в твоем коде стандратную для нее точку входа. [Ответ]
Pengvin 00:48 07.08.2006
ни в коем рази /SUBSYSTEM:WINDOWS если склероз мне не изменяет /SUBSYSTEM:CONSOLE отвечает за консольные проги. [Ответ]
aerin 12:02 07.08.2006

Сообщение от :
ни в коем рази /SUBSYSTEM:WINDOWS

Сообщение от :
error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

Так не бывает. Прилинкованный код библиотеки CRT хочет функцию с именем main(). Вот поэтому я не люблю #pragma, потому что потом хрен найдешь такое включение.
ЗЫ. Ты бы почитал чего-нибудь типа Рихтера, да и покопаться в исходниках CRT не грех, если ты этим собираешься заниматься всерьез, то код некоторых функций приедется выдирать из рантаймовской библиотеки. [Ответ]
Pengvin 00:14 09.08.2006
я бы выдернул или на крайний случай сам бы написал. Там всего то memcpy,memset и strcmp нужен. Так он же (то есть линкер) засранец какие то ___security_cookie и другую ересь требует. Я наверное поищу еще эту функцию. Просто сейчас неохото вплотную заниматься оптимизицией. Просто меня ужаснул размер пустого экзешника. А простое приложение с инициализацией Direct3D весит 1,6 Mб. Это даже на дискету влезает

Я компилил с /NODEFAULTLIB но мне пришлось дописывать libcmt.lib чтобы он находил свои security_cookie. Но он стал требовать _main. Но я в хелпе нашел еще msvcrt.lib и почти все получилось только вот прога компилилась с debagом и пришлось msvctd.lib подключать. Правда еще пришлось в папку с экзешником еще и msvct80.dll кинуть. Вобщем еще та песня.
[Ответ]
aerin 11:07 09.08.2006
Pengvin
Вы уж меня простите, но я констатирую, что у вас напрочь отсутствует понимание вопроса.
libcmt.lib - это и есть с-ный MultiThread-ный run-тайм для статической линковки, от которого мы и избавлялись в начале темы, увеличивает размер итогового экзешника. msvcrt.lib - то же самое, но линковка динамическая, т.е. для запуска нужна еще и MSVCPXX.DLL. Разумеется, оба эти способа требуют от тебя указать точку входа. Так такие вещи не пишутся.

Сообщение от :
Просто сейчас неохото вплотную заниматься оптимизицией. Просто меня ужаснул размер пустого экзешника. А простое приложение с инициализацией Direct3D весит 1,6 Mб. Это даже на дискету влезает

Можно код в студию, а? Ну 40, ну 50 kB, - это нормально для какого-нибудь вращающегося кубика с процедурной текстурой и статическим рантаймом, без всяких ухищрений.

Сообщение от :
Там всего то memcpy,memset и strcmp нужен.

Смотри в папке студии файлы:
../Vc7/crt/src/memcpy.c,
../Vc7/crt/src/memset.c,
../Vc7/crt/src/strcmp.c.
ЗЫ. Почитай все ж чего-нибудь, а? [Ответ]
Pengvin 18:41 09.08.2006
конечно у меня отсутствует понимание вопроса. Я студию практически неделю только вижу. Просто при явно указанной точке входа /ENTRY:WinMain при статической линковке линкер требует main а при динамической нет. Для меня проблема была не в теории а в том что с одной подключенной либой программа собирается а с другой нет.

Сообщение от :
Можно код в студию, а? Ну 40, ну 50 kB, - это нормально для какого-нибудь вращающегося кубика с процедурной текстурой и статическим рантаймом, без всяких ухищрений.

Моя программка занимает при компиляции 40 кб, тут все нормально. Просто я компилировал пример из DirectX SDK он у меня весил 1,67 Мб. Хотя тот же самый пример собранный мелкософтцами прилагаемый к SDK весит 400+ Мб. Так что дело наверное в компиляторе или во мне . [Ответ]
aerin 00:08 10.08.2006
Pengvin
Расскажите все-таки, что вы собираетесь писать: маленькую демку/интро/... или большой серьезный проект? Если первое, то много читать, смотреть исходники CRT, еще читать. Если второе, то пока забить на размер и писать содержательную часть кода. На экзамплы MS особо внимания не обращать, там кстати еще и утечки памяти встречаются И если мне память не изменяет, то в примерах DX SDK они наваяли еще кучу классов-оберток, плюс к этому они там любят линковать картинки к экзешнику. [Ответ]
Pengvin 00:48 11.08.2006
Наверное первое. На большой серьезный проект на подобие игры у меня терпения не хватит. (хотя может быть ) Просто давно хотел изучить студию. А ИМХО лучшего способа что-либо изучить чем решить какую либо задачу нет. Есть конечно языки которые без книги не выучишь, вроде ассемблера.

Сообщение от :
забить на размер и писать содержательную часть кода

Так я на него уже забил. Надоело ошибки линкера давить. Правда с большинством я справился. Для отключения __security_cookie надо было поставить /GS-. Да и сомневаюсь я чтобы мелкософт могли организовать достойную защиту от переполнения буфера.
[Ответ]
aerin 09:29 11.08.2006
Pengvin
Мне кажется, что это немножко не та задача, на которой стоит изучать VC. Органично такие задачи решаются на асме. А в студии такие вещи решаются отказом от большой части стандартного workflow. Скажем так, мощь инструмента несоразмерна задаче.

Сообщение от :
Есть конечно языки которые без книги не выучишь, вроде ассемблера.

Как раз данный случай.

Сообщение от :
Надоело ошибки линкера давить. Правда с большинством я справился. Для отключения __security_cookie надо было поставить /GS-.

Поверьте, большинством этих сообщений линкер пытается вам сказать: "Почитайте книжки". Сообщения не надо "давить", надо писать так, чтоб их не возникало.

Сообщение от :
Да и сомневаюсь я чтобы мелкософт могли организовать достойную защиту от переполнения буфера.

Это какая-то религия? Проще всего сказать, что инструмент плохой... [Ответ]
Pengvin 11:09 12.08.2006
aerin
Я конечно куплю себе книгу по VC. У меня дома валяется какая -то по VC 6 но там только MFC и кусок, стандартной для такого рода книг , теории о ООП. Может быть вы мне что-нибудь посоветуете?
А насчет асма позвольте не согласиться. По моему асм это та крайность, в которую частенько бросаются когда речь заходит об оптимизации. По моему студия и так гененрирует отличный код. Я уже молчу об оптимизации FPU , для меня это вобще темный лес.
PS: Microsoft мне нравиться им можно сказать спасибо хотя бы за DirectX и VC. Но ругать их это - модно. Вот я и не удержался. [Ответ]
Pengvin 12:09 12.08.2006
эээээ. С оптимизмрованным кодом я погараячился.Что то он не сильно оптимизирован. Решил посмотреть ассемблерные листинги.
Вот код на си:

Сообщение от :
char d(char k)
{
char v=k;
v=v*3;
v=v+1;
return v;
}

Вот что выдал компилятор vc v 14.0 c /O2 (Главное если менять опции оптимиизации содержимое не меняется Может я что-то не так делаю.)

Сообщение от :
proc d
mov al, BYTE PTR [esp-4] ;v=k
mov cl, 3
imul cl ;v=v*3
add al, 1 ;v=v+1
endp

Где тут оптимизация. Или компилятор был сделан для компиляции в IL код? А x86 так боком захватили.
Вот что выдал intel c compiler v8.0 c /O2

Сообщение от :
movzx ecx, BYTE PTR [esp+4] ; v=k
lea edx, DWORD PTR [ecx+ecx] ;v=v*2(v+v)
lea eax, DWORD PTR [edx+ecx+1] ;v=v*3(v=v+v+v)+1
movsx eax, al

Ага вот тут попахивает оптимизацией. Замена мат операций на генерацию адреса. Классический метод. Ладно пойду схожу за VC6 потавлю на нее ICC6 и буду жить. [Ответ]
aerin 12:00 14.08.2006
Pengvin

Сообщение от :
Я конечно куплю себе книгу по VC. У меня дома валяется какая -то по VC 6 но там только MFC и кусок, стандартной для такого рода книг , теории о ООП. Может быть вы мне что-нибудь посоветуете?

Я так понимаю, что книга нужна не по VC. VC - это как станок, на котором как ножки для табуреток можно делать, так и высокохудожественные изделия. Я не до конца понимаю, что за софт вы пишете, чтоб что-то советовать. Windows база - Петзольд, VC и MFC - Круглински, Нортон, системные сервисы - Рихтер, Митчел, помимо этого есть куча книг по отдельным аспектам - например, "Отладка в C++" Паппаса и Мюррея. Ну и т.д.

Сообщение от :
А насчет асма позвольте не согласиться. По моему асм это та крайность, в которую частенько бросаются когда речь заходит об оптимизации. По моему студия и так гененрирует отличный код. Я уже молчу об оптимизации FPU , для меня это вобще темный лес.

Не вижу крайностей. Вот отказ от стандартных либ - это крайность. И уж после этого, особой разницы между написанием на C и asm-е не вижу. А в чем траблы с FPU, там команд-то с гулькин хвост? Вот вскякие 3DNow, SSE - там несколько посложнее, но тоже особых сложностей нет. Другое дело, что я очень сильно сомневаюсь, что на достаточно большом куске кода я или вы соптимизируем лучше создателей Intel-ского компайлера. Если только это не демка <10kb, тут еще можно потягаться.

Сообщение от :
эээээ. С оптимизмрованным кодом я погараячился.Что то он не сильно оптимизирован. Решил посмотреть ассемблерные листинги.

Вам надо идти работать тестером, вы на стандартных примерах, получаете какие-то немыслимые результаты

Я убил 20 минут своего времени, пытаясь заставить VC выдать мне add al, 1 - это происходило лишь в случае /Od - т.е. Optimization Disabled. Во всех остальных случаях был честный inc. Кстати, если множитель не тройка, а степень двойки - то умножнеие разворачивается в серию сложений.
Т.е. я хочу сказать, что когда идет битва за такты и байты, то уже нет большой разницы между C и Asm-ом. Считаете, что соптимизируете лучше - пишите функции на Asm-е, нет проблем, благо сейчас машины без сопроцессора вымерли как класс, так что вполне можно юзать FPU незадумываясь.
[Ответ]
Вверх