这是一系列至少两个密切相关但不同的问题的一部分。我希望我分开问他们做对了。

我正在尝试将视觉C ++ 2008应用程序在没有C运行时库的情况下工作。这是一个没有MFC或其他花哨的东西的Win32 GUI应用程序,只需简单的Windows API即可。

因此,我设置了项目属性 - >配置 - > c/c ++ - >高级 - >省略默认库名称为yes(编译器标志) /Zl)并重建。

然后,链接器抱怨未解决的外部 _WinMainCRTStartup. 。公平,我可以告诉链接器使用不同的入口点,说 MyStartup. 。从我在网上聚集的东西来看, _WinMainCRTStartup 做一些初始化的东西,我可能想要 MyStartup 做一个子集。

所以我的问题是: 功能有什么作用 _WinMainCRTStartup 执行,如果我不使用CRT,我可以省略哪些?

如果您了解这些东西,请看看 我的另一个问题 也。谢谢!

撇开:为什么我想首先要这样做?

  1. 我的应用不会明确使用任何CRT功能。
  2. 我喜欢精益和卑鄙的应用。
  3. 它会教我一些新的东西。
有帮助吗?

解决方案

CRT的入口点执行以下(此列表尚未完成):

  • 初始化CRT所需的全球状态。如果没有这样做,则不能使用CRT提供的任何功能或状态。
  • 初始化编译器使用的某些全局状态。 /gs使用的安全cookie之类的运行时间检查肯定在这里脱颖而出。你可以打电话 __security_init_cookie 但是,你自己。您可能需要为其他运行时检查添加其他代码。
  • 在C ++对象上调用构造函数。如果您正在编写C ++代码,则可能需要效仿。
  • 检索OS提供的命令行并启动信息,并将其传递给您。默认情况下,OS没有将参数传递到程序的入口点 - 它们都是由CRT提供的。

Visual Studio可以使用CRT源代码,您可以在调试器中介入CRT的入口点,并确切地找出其在做什么。

其他提示

一个 真的 用C(非C ++)编写的WIN32程序根本不需要任何初始化,因此您可以使用 winmaincrtstartup() 代替 Winmain(Hinstance,...).

也有可能将游戏机程序编写为真正的Win32应用程序,这也是可能的。入口点的默认名称为 _maincrtstartup().

禁用所有额外的代码生成功能,例如堆栈探针,阵列检查等。还可以进行调试。

初始化

有时您需要第一个 hinstance 范围。对于Win32(Win32s除外),它已固定为 (Hinstance)0x400000.

NCMDShow 参数始终是 sw_showdefault.

如有必要,请检索命令行 getCommandline().

终止

当您的程序产生线程时,例如致电 getopenfilename(), ,从 winmaincrtstartup()返回 关键字将悬挂您的程序 - 使用 exitProcess() 反而。

警告

当:

  • 使用大于4 kbytes(每个功能)的堆栈帧(即本地变量)
  • 使用浮点算术(例如float-> int转换)
  • 在32位计算机上使用64位整数(乘,位移动操作)
  • 使用C ++ 新的, 删除, ,以及具有非零以所有会员构造函数的静态对象
  • 使用标准库功能 fopen(), printf() 当然

故障排除

在所有Windows系统上都有一个C标准库(由于Windows 95), msvcrt.dll.

要使用它,请导入他们的入口点,例如使用我的 msvcrt-light.lib (Google为此)。但是仍然有一些警告,尤其是在使用比MSVC6更新的编译器时:

  • 堆栈框架仍然仅限于4个kbytes
  • _ftol_sse 或者 _FTOL2_SSE 必须路由到 _ftol
  • _iob_func 必须路由到 _iob

它的初始化似乎在加载时间运行。至少文件函数将无效运行。

旧问题,但答案要么是不正确的,要么关注一个特定问题。

如果程序实际上在Main/Winmain中启动,则有许多C和C ++功能在Windows(或大多数操作系统)上根本无法使用。

以这个简单的例子:

class my_class
{
public:
    my_class() { m_val = 5; }
    int my_func(){ return m_val }
private:
    int m_val;
}

my_class g_class;

int main(int argc, char **argv)
{
     return g_class.my_func();
}

为了使该程序按预期运行,必须在主之前调用MY_CLASS的构造函数。如果程序完全启动了MAIN,则需要编译器黑客攻击(注意:在某些情况下可以执行此操作)才能在MAIN的一开始插入函数调用。取而代之的是,在大多数OS和大多数情况下,一个不同的函数构造G_CLASS,然后调用Main(在Windows上,这是MainCrtStartup或WinMainCrtStartup;在其他大多数OS上,我习惯的大多数OS是一个称为_start的函数)。

在主要工作之前或之后,还有其他事情C ++,甚至需要完成。主要开始后,Stdin和Stdout(STD :: CIN和STD :: COUT)如何使用?现代如何工作?

C标准需要标准库具有类似posix的信号API,在窗口上必须“安装” windows()。

在大多数OS上,没有系统提供的堆。 C运行时实现了自己的堆(Microsoft的C运行时,只需包装kernel32堆功能)即可。

甚至传递给MAIN,ARGC和ARGV的论点也必须以某种方式从系统中获得。

您可能想看看马特·彼得里克(Matt Pietrick)的文章,以实施自己的C运行时间,以了解如何与Windows + MSVC一起使用(注意:Mingw和Cygwin和Cygwin的特定方面,但实际上都落后于MSVCRT,以实现大多数事情):http://msdn.microsoft.com/en-us/library/bb985746.aspx

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top