.text、.data、.rdata、.reloc 各佔一頁。#pragma comment(linker, "/NODEFAULTLIB")
連結器不再自動引入 libcmt.lib、msvcrt.lib 等。後果:malloc、strcpy、printf 全無定義,必須自行實作或映射至 Win32 API。
| CRT | Win32 替代 | 備註 |
|---|---|---|
| malloc/free | HeapAlloc/HeapFree (GetProcessHeap()) | 需手動管理堆疊控制代碼 |
| strcpy/strcat/strlen | lstrcpy/lstrcat/lstrlen | Kernel32.dll 內建,無匯入庫依賴 |
| strcmp/strcmpi | lstrcmp/lstrcmpi | 區分大小寫/不區分 |
| memcpy/memset/memmove | CopyMemory/FillMemory/MoveMemory | 巨集映射至 RtlMoveMemory 等 |
| sprintf/vsprintf | wsprintf/wvsprintf | 格式支援較少 (無 %f 等) |
| toupper/tolower | CharUpper/CharLower | 單字元/字串雙模式 |
| isalpha/isdigit... | IsCharAlpha/IsCharAlphaNumeric... |
#ifndef _DEBUG
#pragma comment(linker, "/FILEALIGN:16") // 檔案對齊 16 bytes
#pragma comment(linker, "/ALIGN:16") // 記憶體對齊 16 bytes
#pragma comment(linker, "/OPT:REF") // 移除未參考函數/資料
#pragma comment(linker, "/OPT:ICF") // 合併相同 COMDAT
#pragma comment(linker, "/OPT:NOWIN98") // 512 對齊相容舊系統
#pragma comment(linker, "/MERGE:.rdata=.data")
#pragma comment(linker, "/MERGE:.text=.data")
#pragma comment(linker, "/MERGE:.reloc=.data")
#pragma comment(linker, "/ENTRY:WinMain") // 省略 CRT 啟動代碼
#endif
實測:50 行含檔案 I/O、進程建立、字串運算的程式,**1488 bytes**。
LIBCTINY.LIB + 原始碼。_DllMainCRTStartup、malloc、free、memcpy 等極精簡實現。_DllMainCRTStartup 引入完整 CRT 的問題。// 專案屬性 → 連結器 → 輸入 → 忽略所有預設庫
// 附加相依性加入 libctiny.lib
// 進階 → 進入點:_DllMainCRTStartup (或自行實現 DllMain)
| 策略 | 體積 | 開發效率 | 相容性風險 |
|---|---|---|---|
| 完整 CRT + 動態連結 | ~100 KB+ | 最高 | 需目標機安裝 VC++ Redist |
| 靜態連結 CRT | ~300 KB | 高 | 無外部依賴,但體積大 |
| /NODEFAULTLIB + Win32 API | 1-5 KB | 極低 | 字串格式化、浮點、異常處理全無 |
| LIBCTINY | 5-20 KB | 中 | 支援基本 CRT 子集,適合工具類 DLL |
/Zc:dllexportInlines-、/Gy、/O1 (最小體積) 已大幅優化預設輸出。知其然更知其所以然:連結器如何解析符號、區段如何映射記憶體、CRT 做了什麼初始化,才能在體積與功能間做理性取捨。