这是一个系列的至少两个密切相关的,但不同的问题的一部分。 我希望我被分别要求他们做正确的事。
我试图让我的Visual C ++ 2008的应用程序,而无需C运行时库工作。 它没有MFC或其他花哨的东西一个Win32 GUI应用程序,只是普通的Windows API。
所以我设置项目属性- >配置- > C / C ++ - >高级- >省略默认的库名称为Yes(编译器标志/Zl
)和重建。
然后链接器抱怨无法解析的外部_WinMainCRTStartup
。 很公平,我可以告诉链接使用不同的切入点,说MyStartup
。 从我所收集各地的网络, _WinMainCRTStartup
做一些初始化的东西,我可能想MyStartup
做的一个子集。
所以我的问题是: 什么样的功能呢_WinMainCRTStartup
执行,以及这些我可以省略,如果我不使用CRT?
如果你非常了解这个东西,请看看我的其他问题了。 谢谢!
旁白:为什么我想这样做摆在首位?
- 我的应用程序并没有明确使用任何CRT功能。
- 我喜欢精益和平均的应用程序。
- 它会教我一些新的东西。
CRT的入口点执行以下(此列表不完整):
- 初始化由CRT所需的全局状态。 如果不这样做,你不能使用由CRT提供的任何功能或状态。
- 初始化是由编译器使用一些全局状态。 运行时检查,如通过/ GS使用的安全Cookie肯定在这里脱颖而出。 您可以拨打__security_init_cookie但是自己。 您可能需要添加其他代码为其他运行时检查。
- 调用C ++对象构造函数。 如果你正在编写C ++代码,你可能需要仿效这一点。
- 检索命令行并启动OS所提供的信息并传送你的主。 默认情况下,没有参数传递给由OS入口点的程序 - 它们是由CRT所有provied。
CRT的源代码可以使用Visual Studio,您可以通过CRT的入口点的调试步骤,并找出它到底是什么做的。
用C写的(不是C ++) 真正的Win32程序无需任何初始化所有,这样你就可以开始与WinMainCRTStartup(项目),而不是的WinMain(HINSTANCE,...)。
也有可能,但有点难写控制台程序是真正的Win32应用程序; 入口点的默认名称为_mainCRTStartup()。
禁用所有额外的代码生成的功能,如堆叠的探针,阵列检查等调试仍然是可能的。
初始化
有时你需要第一个HINSTANCE参数。 对于Win32(除Win32s中),它被固定到(HINSTANCE)为0x400000。
该参数的nCmdShow总是SW_SHOWDEFAULT。
如果有必要,检索与GetCommandLine命令行()。
终止
当你的程序生成线程,例如通过调用GetOpenFileName(),从WinMainCRTStartup()与return关键字返回时,将挂在你的程序-使用了ExitProcess()来代替。
注意事项
你会遇到相当大的麻烦时:
- 使用堆栈帧(即局部变量)大于4千字节(每个功能)
- 使用浮点运算(例如浮子> INT转换)
- 使用在32位机器(乘法,比特移位操作)64位整数
- 用C ++ 新建 , 删除 ,并与非零出所有成员构造静态对象
- 使用标准的库函数等fopen()函数 ,当然printf()的
疑难解答
目前在所有的Windows系统(自Windows 95)可用C标准库中,MSVCRT.DLL。
要使用它,用我的msvcrt-light.lib(谷歌它)导入他们的切入点,如。 但仍有一些注意事项,使用编译器版本高于MSVC6尤其是当:
- 栈帧仍仅限于4千字节
- _ftol_sse或_ftol2_sse必须路由到_ftol
- _iob_func必须路由到_iob
其初始化似乎在加载时运行。 至少该文件功能将无缝运行。
老问题,但答案是无论是在一个特定的问题或不正确对焦。
有许多的C和C ++的功能,根本不会有适用于Windows(或大多数操作系统,对于这个问题),如果项目实际上是在主/ WinMain函数开始。
就拿这个简单的例子:
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构造函数必须在主被调用。 如果程序在主开始确切地说,它需要一个编译器的黑客(注:GCC做这在某些情况下)插入在主最开始的函数调用。 相反,在大多数操作系统,在大多数情况下,不同的功能构建g_class,然后调用主(在Windows上,这或者是mainCRTStartup或WinMainCRTStartup;在大多数其他操作系统,我习惯了一个名为_start功能)。
还有其他的事情C ++,甚至ç需要对之前完成或之后的主要工作。 如何stdin和stdout(给std :: cin和std ::法院)可用,一旦主开始? 如何atexit对工作的?
C标准要求的标准库有一个类POSIX API信号之前,其主要在Windows上必须“安装”()。
在大多数操作系统,也没有系统提供的堆; C运行时实现自己的堆(微软的C运行时只是包装了的Kernel32堆函数)。
即使传递给主,argc和argv参数,必须从系统以某种方式得到。
你可能想看看关于实施自己的C运行时的细节马特Pietrick的(古)的文章如何与Windows + MSVC(注:MinGW和Cygwin的实施具体的不同的事情,但实际上回落到MSVCRT对大多数事情): http://msdn.microsoft.com/en-us/library/bb985746.aspx