【问题标题】:Visual c++ Compiler/Linker: Problem with Linkerargument /ENTRYVisual c++ 编译器/链接器:Linkerargument /ENTRY 的问题
【发布时间】:2021-01-14 18:15:41
【问题描述】:

几天前,我开始通过 Windows 命令行编译 c++ 代码。 我的目标是尽可能减少输出的大小。 我使用 VS 2019 开发人员命令提示符来执行此操作。

---史前史---

我用cl main.cpp /link /SUBSYSTEM:WINDOWS编译了简单的程序只是为了测试编译,输出大约75kb。 源代码:

int main()
{
    return 0;
}

之后我尝试使用/ENTRY:"main"手动设置入口点

cl main.cpp /link /SUBSYSTEM:WINDOWS /ENTRY:"main"
减少输出大小

Source

我用相同的代码对其进行了测试,它可以工作,现在输出大小约为 3kb。

---实际问题---

这对我来说是一个巨大的成功。 然后我尝试在我的程序中使用标准库,但是当我使用命令编译时:

cl main.cpp /link /SUBSYSTEM:WINDOWS /ENTRY:"main"

源代码:

#include <iostream>
using namespace std;
int main()
{
    cout << "Hello" << endl;
    return 0;
}

它给了我很多错误,我不明白。 Errors 我在整个互联网上搜索它们,但一无所获。 我发现错误必须与标准库 std 和链接器参数“/ENTRY:”main“”有关。

所以我的问题是:为什么我不能将"/ENTRY:"main"" 与标准库一起使用?

(抱歉我的拼写错误,我不是母语人士)

【问题讨论】:

  • 在调用使用任何需要操作系统的东西的 main() 之前完成了很多初始化工作。在 main 上放置一个断点并检查调用堆栈以查看发生了什么。

标签: c++ linker std


【解决方案1】:

main 绝不是任何 C 或 C++ 程序中可执行文件的入口点。 /ENTRY: main 在缩小代码时“起作用”的原因是,您已经丢弃了对使程序实际工作所必需的许多 C 库初始化代码的引用——您只是还没有探索后果,因为您使用简单的代码来“测试”这样的黑客。以下只是您面临的问题的一个简短示例;

  1. argcargv 你进入main 有无效值,

  2. 没有调用静态对象的构造函数,

  3. 大量运行时的实现细节未初始化,例如stdout 无效,因此一个简单的printf,实际上意味着fprintf(stdout, ...) 将不起作用。

这只是冰山一角。基本上,你破坏了一切。我想说:感谢链接器最终阻止你继续这个毫无意义的实验。

重新实现一个开销最小的 C 和 C++ 库是一项相当多的工作,重点在于您不需要任何技巧:您只需禁用与默认标准库的链接,然后链接而是使用替换,这将取决于该替换来实现,这样您就不需要自定义 /ENTRY 点或其他类似的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 2012-01-16
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2016-03-28
    相关资源
    最近更新 更多