Linker options

本文详细解析了在Win32环境下,C/C++编译器的#pragmacomment指令与链接器选项/SUBSYSTEM和/ENTRY的使用方法。通过这些选项,可以指定应用程序的子系统类型(如CONSOLE或WINDOWS)和入口点函数,适用于不同类型的Windows应用程序。

一  一段代码

#if defined(WIN32)
    #ifdef NDEBUG
        #pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
    #else
        #pragma comment(linker, "/SUBSYSTEM:CONSOLE")
    #endif
#endif

二 代码解释

1  pragma comment

#pragma comment( comment-type [,"commentstring"] )

comment-type:compiler | exestr | lib | linker | user 

2 linker options

(1)/SUBSYSTEM :通知操作系统如何运行 .exe 文件。

/SUBSYSTEM:{BOOT_APPLICATION|CONSOLE|EFI_APPLICATION|  
            EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|  
            POSIX|WINDOWS)  
            [,major[.minor]] 

其中:

CONSOLE
Win32 字符模式应用程序。 操作系统为各种控制台应用程序提供控制台。 如果为本机代码定义了 main 或 wmain,为托管代码定义了 int main(array<String>),或者完全使用 /clr:safe 构建应用程序,则CONSOLE是默认值。

WINDOWS
应用程序不需要控制台,原因很可能是它会创建自己的窗口来与用户进行交互。 如果为本机代码定义了 WinMain 或 wWinMain,或为托管代码定义了 WinMain(HISTANCE *, HINSTANCE *, char *, int) 或 wWinMain(HINSTANCE *, HINSTANCE *, wchar_t *, int),则 WINDOWS 是默认值。

在 Visual Studio 开发环境中设置此链接器选项:

1.打开项目的“属性页” 对话框。
2.选择链接器文件夹。
3.选择系统属性页。
4.修改SubSystem属性。

(2)/ENTRY  : 设置起始地址。

/ENTRY:function 

function取值:

功能名称默认值为
mainCRTStartup (或wmainCRTStartup)使用 /subsystem: console; 的应用程序调用main(或wmain)An application that uses /SUBSYSTEM:CONSOLE; calls main (or wmain)
WinMainCRTStartup (或wWinMainCRTStartup)使用 /SUBSYSTEM 的应用程序:WINDOWS; 调用WinMain(或wWinMain),必须对其进行定义以使用 __stdcallAn application that uses /SUBSYSTEM:WINDOWS; calls WinMain (or wWinMain), which must be defined to use __stdcall
_DllMainCRTStartupDLL;调用DllMain如果存在,其必须进行定义以使用 __stdcall

 在 Visual Studio 开发环境中设置此链接器选项
1.打开项目的“属性页” 对话框。
2.单击链接器文件夹。
3.单击高级属性页。
4.修改入口点属性。

三 参考

comment (C/C++) 

linker options

在Keil MDK(μVision)开发环境中,**Linker(链接器)** 是项目配置中负责管理内存布局、段合并和地址分配的关键模块。以下是其核心功能及配置方法: --- ### **Linker的主要作用** 1. **内存映射管理** 通过链接脚本(`.sct`文件)定义代码/数据的存放区域(如Flash、RAM),例如: ```plaintext LR_IROM1 0x08000000 0x00080000 { ; 定义Flash区域(地址+大小) ER_IROM1 0x08000000 0x00080000 { ; 代码执行区 *.o (RESET, +First) ; 启动文件优先放置 *(InRoot$$Sections) ; 特殊段 .ANY (+RO) ; 所有只读段(代码、常量) } RW_IRAM1 0x20000000 0x00010000 { ; 定义RAM区域 .ANY (+RW +ZI) ; 已初始化/未初始化数据 } } ``` 2. **段合并与优化** - 将分散的`.o`文件中的相同属性段(如`.text`、`.data`)合并到连续内存。 - 移除未使用的函数和变量(需开启优化选项)。 3. **地址分配** 为函数、变量分配最终运行地址,确保与硬件内存对齐。 --- ### **配置Linker的步骤** 1. **打开链接器设置** - 菜单栏:**Project** → **Options for Target** → **Linker** 标签页。 - 或右键项目中的目标设备(如`Target 1`)→ **目标选项** → **Linker**。 2. **关键配置项** - **Use Memory Layout from Target Dialog** 勾选后,链接器使用**Target**标签页中定义的内存配置(推荐新手使用)。 - **Scatter File** 手动指定自定义的`.sct`文件路径(适用于复杂内存布局)。 - **Ro-Base** / **Rw-Base** 覆盖`.sct`文件中的代码(RO)和数据(RW)基地址(需谨慎使用)。 - **Others** - **Disable Warning 63**:忽略未使用的段警告。 - **Sort by Alignment**:优化段对齐以减少内存碎片。 3. **生成Map文件** 在**Linker**标签页勾选**Generate linker map file**,生成`.map`文件查看详细内存分配: ```plaintext Memory Map of the image Image component sizes Cross Reference Table ``` --- ### **常见问题解决** 1. **错误:`Not enough information to list image symbols`** - 原因:未生成Map文件或符号表缺失。 - 解决:勾选**Generate linker map file**,并确保编译选项中启用了符号生成(如`--debug`)。 2. **错误:`No memory region specified for load region`** - 原因:`.sct`文件中未正确定义加载区域(LR)或执行区域(ER)。 - 解决:检查`.sct`文件语法,确保每个LR包含至少一个ER。 3. **优化内存占用** - 在**Linker**标签页启用**Remove Unused Sections**(需配合编译器优化选项如`-O2`)。 --- ### **示例:自定义链接脚本** 若需手动编写`.sct`文件(如多核处理器或非标准内存),参考以下模板: ```plaintext ; 定义两个内存区域:Flash和RAM LR_IROM1 0x08000000 0x00100000 { ; Flash: 1MB ER_IROM1 0x08000000 0x000E0000 { ; 代码区: 912KB *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } ER_IROM2 0x080E0000 0x00020000 { ; 固定数据区: 128KB .ANY (+RO_CONST) } } RW_IRAM1 0x20000000 0x00020000 { ; RAM: 128KB .ANY (+RW +ZI) } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值