线程入口点函数
线程必须指定要执行的入口点函数,我们已经知道主线程的入口点函数是_tmain/_tWinMain。手动创建线程时,其入口点函数格式如下:
线程入口点函数可以执行你指定的任何操作。线程在入口点函数返回时停止运行,系统释放线程栈,并将线程内核对象引用计数减1,如果引用计数变为0,系统会销毁线程内核对象。和进程内核对象类似,线程内核对象的生存期可能要比线程本身的生存期更长。
下面是线程入口点函数需要注意的一些地方:
- 主线程入口点函数必须命名为main/wmain/WinMain/wWinMain(如果要使用别的入口点函数,可以在工程属性的“链接器”中将/ENTRY选项设置为相应的函数名),而手动创建的线程入口点函数的命名是任意的,只要符合C/C++语言标识符规范既可
- 线程入口点函数的参数是void指针,这意味着你可以向其传递任何自定义的参数
- 线程入口点函数必须返回一个值,返回值将作为线程的退出码
- 线程入口点函数应该尽量使用函数参数和非静态局部变量。当你在线程函数内使用静态和全局变量时,可能会引发多线程读写数据冲突的问题,由于参数和局部变量是在线程栈上创建的,在不同线程之间是独立的,因而不用担心读写冲突
你已经知道如何定义线程入口点函数了,接下来我们会讨论操作系统如何创建线程并执行线程入口点函数。
附注
使用VC编译器时,IDE默认将应用的入口点函数设置为CRT启动函数(mainCRTStartup/wmainCRTStartup/WinMainCRTStartup/wWinMainCRTStartup),在VS工程属性的“链接器”选项卡中,你可以将入口点/ENTRY设置为任何自定义的函数,但这样做是危险的,CRT启动函数负责初始化CRT的一切资源,如果不执行CRT启动函数,你的代码也就不应该试图访问任何CRT变量/函数等等。举个最简单的例子:
新建一个windows console空项目,添加上面的代码,此时程序的默认入口点函数是mainCRTStartup。在main的返回语句前设置断点,调试并观察argc和argv的值,分别是1和应用的启动路径。接下来将工程的/ENTRY选项设置为main,再次调试,这时你会发现argc和argv的值都变为无效。这也符合MSDN对/ENTRY的阐述“建议让链接器设置入口点,以便 C 运行时库正确初始化,并执行静态对象的 C++ 构造函数”。