1.使用CreateThread创建线程,其中第三个参数是LPTHREAD_START_ROUTINE lpStartAddress,
而LPTHREAD_START_ROUTINE被定义为
typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(
LPVOID lpThreadParameter
);
#define WINAPI __stdcall
也就是线程入口函数应该是__stdcall方式。
为什么?(我的想法,不一定正确)
因为线程入口函数和一般的函数调用不一样,在这里调用者(创建新线程的函数)并不知道被调用者(新线程入口函数)什么时候返回,
调用者也就没法在被调用者调用结束后清理参数栈,所以必须有被调用者自己在退出时清理参数栈。
所以为__stdcall方式。
2. 编写C/C++程序,创建线程应使用_beginthread函数。
而_beginthread函数的第一个参数是void (__cdecl * _StartAddress) (void *),需要__cdecl方式的函数。
这是怎么回事?
(1) 其实_beginthread内部调用了CreateThread,它是这样调用的:
ptd->_initaddr = (void *) initialcode;
ptd->_initarg = argument;
CreateThread( NULL,
stacksize,
_threadstart,
(LPVOID)ptd,
CREATE_SUSPENDED,
(LPDWORD)&(ptd->_tid) ))
也就是说,他创建的线程入口函数是_threadstart,而_threadstart原型:
static unsigned long WINAPI _threadstart(void *); 也就是__stdcall方式。
(2)_threadstart内部再调用_callthreadstart,_callthreadstart原型:
static void _callthreadstart(void);
(3)最后由_callthreadstart调用我们的线程函数
__try
{
( (void(__CLRCALL_OR_CDECL *)(void *))(((_ptiddata)ptd)->_initaddr) )
( ((_ptiddata)ptd)->_initarg );
_endthread();
}
在线程结束后,它会调用_endthread,清理C/C++运行期资源。
3.在《Windows核心编程》中说终止进程的运行的最好方式是主线程的进入点函数返回 ,这样能保证所有线程资源能够得到正确清除。
实际上使用下面这个例子:
程序的运行结果如下:
A::A(global)
A::A(thread_func)
A::~A(global)
可见线程thread_func中的local_a析构函数未被调用,仍然可能有资源泄漏。可见,每一个线程函数也都要小心,要确保在主线程结束之前能正常退出,而主线程也要能保证所有其他线程正常退出后再退出。