windows核心编程之 C/C++运行库注意事项
文章目录
- 1. 用`_beginthreadex`而不要用`CreateThread`创建线程
- 2. 绝对不应该调用的C/C++运行库函数
- 3. 了解自己的身份
标准C/C++运行库最初不是为多线程应用程序而设计。在多线程环境中会出现问题的C/C++运行库变量和函数有
errno
,_deserrno
,strtok
,_wcstok
,strerror
,_strerror
,tmpnam
,tmpfile
,asctime
,_wasctime
,gmtime
,_ecvt
和_fcvt
等。创建新线程时,一定不要调用操作系统的
CreateThread
函数,相反,必须调用C/C++运行库函数_beginthreadex
uintptr_t _beginthreadex( // NATIVE CODEvoid *security,unsigned stack_size,unsigned ( __stdcall *start_address )( void * ),void *arglist,unsigned initflag,unsigned *thrdaddr
);
uintptr_t _beginthreadex( // MANAGED CODEvoid *security,unsigned stack_size,unsigned ( __clrcall *start_address )( void * ),void *arglist,unsigned initflag,unsigned *thrdaddr
);
_beginthreadex
函数的参数列表与CreateThread
函数的一样,但是参数名称和类型并不完全一样。这是因为 Microsoft 的 C/C++运行库开发组认为,C/C++运行库函数不应该对 Windows 数据类型有任何依赖。 _beginthreadex
函数也会返回新建线程的句柄,就像CreateThread
那样。所以,如果已经在自己的源代码中调用了CreateThread
函数,可以非常方便地用_beginthreadex
来全局替换所有CreateThread
。但是,由于数据类型并不完全相同,所以可能还必须执行一些类型转换,以便顺利地通过编译。
对于_beginthreadex
函数,需要重点关注以下几点:
- 每个线程都有自己的专用
_tiddata
内存块,它们是从C/C++运行库的堆(heap)上分配的。 - 传给
_beginthreadex
的线程函数的地址保存在_tiddata
内存块。 _beginthreadx
确实会在内部调用CreateThread
,因为操作系统只知道用这种方式来创建一个新线程。CreateThread
函数被调用时,传给它的函数地址是_threadstartex
(而非pfnStartAddr
)。另外,参数地址是_tiddata
结构的地址,而非pvParam
。- 如果一切顺利,会返回线程的句柄,就像
CreateThread
那样。任何操作失败,会返回0。
1. 用_beginthreadex
而不要用CreateThread
创建线程
- 加入线程使用了C/C++运行库的
signal
函数,则整个进程都会终止,因为结构化异常处理(SEH)帧没有就绪。 - 加入假如线程不是通过调用
_endthreadex
来终止的,数据块就不能被销毁,从而导致内存泄露。
2. 绝对不应该调用的C/C++运行库函数
C/C++运行库还包括以下两个函数:
uintptr_t _beginthread( // NATIVE CODEvoid( __cdecl *start_address )( void * ),unsigned stack_size,void *arglist
);
uintptr_t _beginthread( // MANAGED CODEvoid( __clrcall *start_address )( void * ),unsigned stack_size,void *arglist
);void _endthread(void);
新的_beginthreadex
和_endthreadex
函数已经取代了这两个传统的函数。可以看出_beginthread
函数的参数较少,所以和全功能的_beginthreadex
函数相比,它的局限性比较大。例如使用_beginthread
函数,不能创建具有安全属性的线程,不能创建让线程立即挂起,也不能获得线程ID值。_endthread
函数的情况与此类似:它是无参的,这意味着线程的退出代码被硬编码为0。
3. 了解自己的身份
Windows提供了一些函数来方便线程引用它的进程内核对象或者它自己的线程内核对象:
HANDLE GetCurrentProcess();
HANDLE GetCurrentThread();
线程可以通过以下函数来查询其进程的唯一ID或它自己的唯一ID
DWORD GetCurrentProcessId();
DWORD GetCurrentThreadId();
windows核心编程之 C/C++运行库注意事项相关推荐
- unity连接linux服务器,C#编程之C#通过SharpSSH库与Linux服务器建立SSH连接并执行命令...
本文主要向大家介绍了C#编程之C#通过SharpSSH库与Linux服务器建立SSH连接并执行命令,通过具体的内容向大家展示,希望对大家学习C#编程有所帮助. 在Unity3D项目开发工具时需要用到S ...
- Windows网络编程之Winsock 编程接口实验
实验一 Winsock 编程接口实验 1 实验类型 验证型实验 2 实验目的 1. 掌握Winsock 的启动和初始化: 2. 掌握gethostname(),gethostbyname(),GetA ...
- 随想录(最简单的windows图形编程之Easyx)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 对于很多使用过Turbo C的同学来说,以前使用编译器进行图形编程是一件非常容易的事情.但是在 ...
- windows 声音编程之waveout
本教程将帮助您了解如何使用Windows waveOut接口播放数字音频.根据经验,这些接口函数掌握起来有些困难.在本教程中,我们将会建立一个Windows命令行程序来原始数字音频.注意:本教程假设您 ...
- windows Socket编程之TCP服务端与客户端
在前面的文章中有一篇讲到了命名管道通信,它是创建一根管道来进行进程之间或网络之间通信的.但是它有些缺陷,比如说效率较低等.而从这篇文章开始将介绍socket编程.socket是通过TCP,UDP,IP ...
- JavaWeb核心编程之Tomcat安装和配置
什么是JavaWeb 在Sun的Java Servlet规范中, 对Java Web应用做了这样的定义: "Java Web应用由一组Servlet, HTML页面, 类, 以及其他可以被绑 ...
- Windows Socket编程之TCP实现大文件的传输
前言: UDP版本可参考被人博客: http://blog.csdn.net/luchengtao11/article/details/71016222 本文所述代码工程托管在Github: http ...
- Hadoop 核心编程之 HDFS 的文件操作
前言 本文并没有打算介绍 HDFS 的读写流程,虽然这是一块比较重要的内容.如果你感兴趣,可以去搜索相关资料.如果一遍没有看懂,请看第二遍. 本文还是以代码为主,并附以简短的说明,帮助你理解代码的逻辑 ...
- Delphi D10.X 并行库PPL编程之TTask
Delphi D10.X 并行库PPL编程系列之 TTask delphi中的RTL(运行库)提供了并行编程库(PPL --Parallel Programming Library) ,让您的应用程序 ...
- cx_oracle windows缺少100 dll,Windows10无法运行QQ提示缺少MSVCR100.dll的解决方案
QQ是一款广受用户喜爱的即时通讯软件,我们在工作和生活中都经常会使用到它.不过,一些用户反馈在win10 32位系统中双击打开QQ后,会出现缺少MSVCR100.dll的提示,且QQ无法运行,那是怎么 ...
最新文章
- Linux中的防火墙----iptables
- PHP 设计模式之原型模式
- android base64encoder 不存在
- 用户登录界面 - 记事本风格HTML代码
- 重启用reboot后起不来_2021年中国“天眼”开放,美媒记者探访后感叹了……
- Android中Dialog对话框
- TCP/IP协议讲解
- 如何填写台式计算机参数,教你如何看懂电脑各配置参数
- Unity手势插件FingerGestures
- python汇率的转换程序_如何实现python汇率转换代码
- 阿姆达尔定律(Amdahl’s Law)
- 【数据结构】Java实现栈
- 一维信号小波阈值去噪
- 输出一个 n 阶的方阵
- 推荐系统_基于内容的推荐
- 论文投稿指南——中文核心期刊推荐(原子能技术)
- PyQt5学习:QLabel 标签控件两种 自适应缩放显示图片 方法比较
- 数字化工厂的定义及建设目标和意义
- Qt编写物联网管理平台1-项目框架
- 对编程相关的某些概念的思考