Windows核心编程 --- 线程创建(CreateThread和_beginthreadex的区别)

CreateThread和_beginthreadex的是Windows编程和C/C++中创建线程的方法,所传入的参数都是一样的

在_beginthreadex的内部就是调用了CreateThread API。

区别:

1._beginthreadex创建的每个线程都会有自己专用的_tiddata内存块,这是在堆上分配的,并且ThreadProc和Param都会保存在_tiddata这个结构体中。

2.在_beginthreadex中会调用CreateThread不会直接调用ThreadProc而会注册_threadstartex函数。

_threadstartex内部会先对_tiddata进行初始化,然后会调用_callthreadstartex,在这个CALL内部调用ThreadProc,传递的参数之前保存在_tiddata中的原本的参数,最后将返回值作为参数传递给_endthreadex,在_endthreadex中对_tiddata进行释放,最后调用ExitThread进行终止线程。


用x32dbg加载符号跟一下调用_beginthreadex的整个过程:

一,调用_beginthreadex,利用create_thread_parameter()初始化_tiddata,将其作为参数传入CreateThread



二,利用CreateThread后最先到达ntdll.RtlUserThreadStart



三,调用运行库的thread_start函数


四,跟进thread_start,这里通过getptd重新获取到 * _tiddata,并且调用ThreadProc,一直等待ThreadProc函数执行完毕返回才继续下面处理。



五,调用_endthread进行线程的终止以及_tiddata结构体的释放


流程如下:

_beginthreadex()初始化_tiddata ---> CreateThread(_tiddata,_threadstartex) ---> RtlUserThreadStart ---> thread_start -调用ThreadProc --> _endthreadex( )释放_tiddata并且调用RtlExitUserThread,就不会走正常的CreateThread的终止流程


之所以在调用了C\C++的程序中用_beginthreadex而不用CreateThread的原因就是因为在线程中调用runtime函数会用到tiddata结构体中的内容,如果用CreateThread进行创建一个C\C++的调用了某些运行库中会用到tiddata的函数,检测到tiddata为NULL,C\C++运行库函数就会分配初始化一个_tiddata块,然后通过TlsSetValue与线程关联,只不过这样线程就不会进行清理_tiddata结构体的工作,这样就造成了内存泄漏。但是也不能直接用_endthreadex来终止掉线程,因为这样虽然会清理掉_tiddata但是由于ExitThread的调用就会造成线程中类的成员不能调用析构函数。



阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭