vc編譯exe的體積最小優(yōu)化

參考鏈接:vc編譯exe的體積最小優(yōu)化

人們都說(shuō) vc 做出的東西可以小點(diǎn),現(xiàn)在你打開(kāi)vc編譯一個(gè)Hello World出來(lái)!點(diǎn)屬性看下,咦!我沒(méi)走眼吧,就一Hello World就160kb真是要人命啊!
呵呵!上面的情況是筆者所遭遇的情況.不過(guò)后來(lái)了解vc可以通過(guò)設(shè)置參數(shù)來(lái)自定義編譯方式.為什么文件那么大!主要是編譯器加入了很多沒(méi)必要的代碼(這里是對(duì)我們而言,不過(guò)有些代碼還是有利于安全的).好了我們就手動(dòng)改下編譯器的參數(shù)來(lái)看看能到多大!

我們主要用到的技巧有:

一,使用release版而不用debug版編譯

使用debug版編譯會(huì)生成許多垃圾信息.我們先使用默認(rèn)的設(shè)置進(jìn)行一下編譯.可以看到編譯后生成的文件有152k之巨.使用release版編譯具體方法是:在"build(編譯)--->Configuration(配置)"中將"Win32 debug"移去,然后再次編譯可以發(fā)現(xiàn)文件已經(jīng)小了很多,才24k.但離我們的目標(biāo)還很遠(yuǎn)呢.

二,設(shè)置自己的入口點(diǎn)函數(shù)

C或C++程序默認(rèn)的入口函數(shù)是main()或WinMain(),但我們現(xiàn)在不用什么Main,WinMain.因?yàn)檫@些都不是直接的入口點(diǎn),編譯器在產(chǎn)生exe文件的時(shí)候,將為我們生成真正的入口點(diǎn).下面我們來(lái)定義自己的入口函數(shù),具體是把main或WinMain改成其它的名字(如MyFun),打開(kāi)"Project(工程)--->settings(設(shè)置)"選項(xiàng),選中"link"選項(xiàng)卡,在"Category(分類(lèi))"下拉列表中選"output",在" Entry-Point symbol(輸入項(xiàng)-點(diǎn)符號(hào))"中輸入我們剛才定義的入口函數(shù)(MyFun),在源程序中也要做相應(yīng)修改,然后再編譯.現(xiàn)在是16k了:)

三,更改編譯對(duì)齊方式

通常VC在編譯的時(shí)候,采用的對(duì)齊方式是0x1000,即4096bytes,我們現(xiàn)在將他改成0x200,即512bytes.

在剛才打開(kāi)的"link"選項(xiàng)卡,在下面的"Project options(工程選項(xiàng))"中添加:/align:512(還可以將512設(shè)

置的更小如16,32.....).注意兩個(gè)參數(shù)之間有個(gè)空格. 3k了_用32試試 1.84k好~~~用16 1.79k天哪!

再把程序的數(shù)據(jù)段和代碼段放在一起,添加:/merge.data=.text /merge:.rdata=.text 1.76k go on!

另外,如果要是用到MFC函數(shù)的程序,可在"Project(工程)--->settings(設(shè)置)"里面的"通用(General)"選項(xiàng)卡中在"Microsoft Foundation Classes"中選擇使用一個(gè)MFC的dll(Use MFC in a Share Dll)也會(huì)使文件大小縮小很多.現(xiàn)在我們的超小后門(mén)編譯好了,試下能用否. ok 沒(méi)問(wèn)題哦

大家注意到程序運(yùn)行時(shí)會(huì)產(chǎn)生一個(gè)cmd窗口,要讓他沒(méi)有就好了.這也好辦.

回到VC++中,在"Project(工程)--->settings(設(shè)置)"選項(xiàng),選中"link"選項(xiàng)卡,在下面的"Project options(工程選項(xiàng))"有/subsystem:console選項(xiàng),表示程序是控制臺(tái)程序,雙擊運(yùn)行是會(huì)有一個(gè)cmd窗口,把console改為windows就沒(méi)有窗口了.:),運(yùn)行一下 沒(méi)有窗口哦 但有進(jìn)程 連接一下試試

ok 沒(méi)問(wèn)題 這樣我們的超小1.76k telnet小后門(mén)就成功了 不被查殺哦 _

// 編譯器 cl.exe(Visual C++ 6.0)
// 沒(méi)有做任何優(yōu)化情況下,編譯大小為:16K
// 編譯優(yōu)化后: 1K (用16進(jìn)制編輯器把尾部的0x00去掉: 712bytes)
#include <windows.h>
#pragma comment(lib,"kernel32.lib")

// 作用: 指定節(jié)對(duì)齊為512字節(jié)
#pragma comment(linker, "/align:512")

// 作用: 合并節(jié)
// 將.data節(jié)和.rdata節(jié)合并到.text節(jié)(代碼節(jié))
#pragma comment(linker, "/merge:.data=.text")
#pragma comment(linker, "/merge:.rdata=.text")

// 作用: 指定子[系統(tǒng)](https://www.2cto.com/os/)為windows (和優(yōu)化無(wú)關(guān))
// vc編譯器默認(rèn)是console,會(huì)有個(gè)黑糊糊的CMD窗口,不好看.用windows就好了
#pragma comment(linker, "/subsystem:windows")

// 作用: 指定入口函數(shù)
// 子系統(tǒng)為windows的默認(rèn)入口點(diǎn)WinMain和console的默認(rèn)入口點(diǎn)main,都會(huì)引入

#pragma comment(linker, "/ENTRY:main")

//int WinMain(HINSTANCE current, HINSTANCE prev, LPSTR cmdline, int
//showcmd)

// 作用: 去掉函數(shù)的棧幀代碼,純屬吹毛求疵:-)
// 即函數(shù)開(kāi)頭的push ebp / mov ebp, esp和結(jié)尾的pop ebp / retn
__declspec(naked)
void main()
{
// 調(diào)用wmp. 這是按套路出牌的方法.
//typedef VOID (__stdcall *fnRunDllW)(HWND, HINSTANCE, LPCWSTR, DWORD);
//((fnRunDllW)GetProcAddress(LoadLibrary("msdxm.ocx"), "RunDllW"))(0,0,0,0);

// 不按套路出牌,不壓入RunDllW的函數(shù)參數(shù),直接調(diào)用.
//GetProcAddress(LoadLibrary("msdxm.ocx"), "RunDllW")();
MessageBox(0,0,0,0);
// 注意此時(shí)的堆棧是不平衡的.
// 但是通過(guò)ExitProcess()退出自身,就不用去考慮平衡了.
ExitProcess(0);
}

微軟C/C++ 編譯器選項(xiàng)

-優(yōu)化-

/O1
最小化空間

/Op[-]
改善浮點(diǎn)數(shù)一致性

/O2
最大化速度

/Os
優(yōu)選代碼空間

/Oa
假設(shè)沒(méi)有別名

/Ot
優(yōu)選代碼速度

/Ob<n>
內(nèi)聯(lián)展開(kāi)(默認(rèn) n=0)

/Ow
假設(shè)交叉函數(shù)別名

/Od
禁用優(yōu)化(默認(rèn)值)

/Ox
最大化選項(xiàng)。(/Ogityb2 /Gs)

/Og
啟用全局優(yōu)化

/Oy[-]
啟用框架指針省略

/Oi
啟用內(nèi)部函數(shù)

-代碼生成-

/G3
為 80386 進(jìn)行優(yōu)化

/GH
啟用 _pexit 函數(shù)調(diào)用

/G4
為 80486 進(jìn)行優(yōu)化

/GR[-]
啟用 C++ RTTI

/G5
為 Pentium 進(jìn)行優(yōu)化

/GX[-]
啟用 C++ EH(與 /EHsc 相同)

/G6
為 PPro、P-II、P-III 進(jìn)行優(yōu)化

/EHs
啟用 C++ EH(無(wú) SEH 異常)

/GB
為混合模型進(jìn)行優(yōu)化(默認(rèn))

/EHa
啟用 C++ EH(w/ SEH 異常)

/Gd
__cdecl 調(diào)用約定

/EHc
外部“C”默認(rèn)為 nothrow

/Gr
__fastcall 調(diào)用約定

/GT
生成纖維安全 TLS 訪問(wèn)

/Gz
__stdcall 調(diào)用約定

/Gm[-]
啟用最小重新生成

/GA
為 Windows 應(yīng)用程序進(jìn)行優(yōu)化

/GL[-]
啟用鏈接時(shí)代碼生成

/Gf
啟用字符串池

/QIfp[-]
啟用 Pentium FDIV 修復(fù)

/GF
啟用只讀字符串池

/QI0f[-]
啟用 Pentium 0x0f 修復(fù)

/Gy
分隔鏈接器函數(shù)

/QIfist[-]
使用 FIST 而不是 ftol()

/GZ
啟用堆棧檢查 (/RTCs)

/RTC1
啟用快速檢查 (/RTCsu)

/Ge
對(duì)所有函數(shù)強(qiáng)制堆棧檢查

/RTCc
轉(zhuǎn)換為較小的類(lèi)型檢查

/Gs[num]
控制堆棧檢查調(diào)用

/RTCs
堆棧幀運(yùn)行時(shí)檢查

/GS
啟用安全檢查

/RTCu
未初始化的本地用法檢查

/Gh
啟用 _penter 函數(shù)調(diào)用

/clr[:noAssembly]
為公共語(yǔ)言運(yùn)行時(shí)庫(kù)編譯noAssembly - 不產(chǎn)生程序集

-輸出文件-

/Fa[file]
命名程序集列表文件

/Fo<file>
命名對(duì)象文件

/FA[sc]
配置程序集列表

/Fp<file>
命名預(yù)編譯頭文件

/Fd[file]
命名 .PDB 文件

/Fr[file]
命名源瀏覽器文件

/Fe<file>
命名可執(zhí)行文件

/FR[file]
命名擴(kuò)展 .SBR 文件

/Fm[file]
命名映射文件

-預(yù)處理器-

/AI<dir>
添加到程序集搜索路徑

/Fx
將插入的代碼合并到文件

/FU<file>
強(qiáng)制使用程序集/模塊

/FI<file>
命名強(qiáng)制包含文件

/C
不抽出注釋

/U<name>
移除預(yù)定義宏

/D<name>{=|#}<text>
定義宏

/u
移除所有預(yù)定義宏

/E
預(yù)處理到 stdout

/I<dir>
添加到包含搜索路徑

/EP
預(yù)處理到 stdout,沒(méi)有 #line

/X
忽略“標(biāo)準(zhǔn)位置”

/P
預(yù)處理到文件

-語(yǔ)言-

/Zi
啟用調(diào)試信息

/Zl
忽略 .OBJ 中的默認(rèn)庫(kù)名

/ZI
啟用“編輯并繼續(xù)”調(diào)試信息

/Zg
生成函數(shù)原型

/Z7
啟用舊式調(diào)試信息

/Zs
只進(jìn)行語(yǔ)法檢查

/Zd
僅有行號(hào)調(diào)試信息

/vd{0|1}
禁用/啟用 vtordisp

/Zp[n]
在 n 字節(jié)邊界上包裝結(jié)構(gòu)

/vm<x>
指向成員的指針類(lèi)型

/Za
禁用擴(kuò)展(暗指 /Op)

/noBool
禁用“bool”關(guān)鍵字

/Ze
啟用擴(kuò)展(默認(rèn))

/Zc:arg1[,arg2]
C++ 語(yǔ)言一致性,這里的參數(shù)可以是:forScope - 對(duì)范圍規(guī)則強(qiáng)制使用標(biāo)準(zhǔn) C++;wchar_t - wchar_t 是本機(jī)類(lèi)型,不是 typedef

  • 雜項(xiàng) -

@<file>
選項(xiàng)響應(yīng)文件

/wo<n>
發(fā)出一次警告 n

/?, /help
打印此幫助消息

/w<l><n>
為 n 設(shè)置警告等級(jí) 1-4

/c
只編譯,不鏈接

/W<n>
設(shè)置警告等級(jí)(默認(rèn) n=1)

/H<num>
最大外部名稱(chēng)長(zhǎng)度

/Wall
啟用所有警告

/J
默認(rèn) char 類(lèi)型是 unsigned

/Wp64
啟用 64 位端口定位警告

/nologo
取消顯示版權(quán)消息

/WX
將警告視為錯(cuò)誤

/showIncludes
顯示包含文件名

/WL
啟用單行診斷

/Tc<source file>
將文件編譯為 .c

/Yc[file]
創(chuàng)建 .PCH 文件

/Tp<source file>
將文件編譯為 .cpp

/Yd
將調(diào)試信息放在每個(gè) .OBJ 中

/TC

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,716評(píng)論 0 5
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說(shuō)明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,979評(píng)論 0 9
  • 在C語(yǔ)言中,五種基本數(shù)據(jù)類(lèi)型存儲(chǔ)空間長(zhǎng)度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來(lái)閱讀 4,044評(píng)論 0 2
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問(wèn)題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 8,133評(píng)論 0 27
  • feisky云計(jì)算、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 4,355評(píng)論 0 5

友情鏈接更多精彩內(nèi)容