在用visual studio进行界面编程时(如MFC),前台UI我们能够通过MFC的消息循环机制实现。而对于后台的数据处理。我们可能会用到多线程来处理。

那么对于大多数人(尤其是我这样的菜鸟),一个比較快捷的方法便是选择MFC多线程:AfxBeginThread或者CreateThread来进建立多线程。当一两个线程还是能够得。当有3个或者3个以上的线程出现时,极可能出现内存泄漏。原因分析例如以下:

CWinThread的多线程不安全性:

由于 CWinThread 会调用_beginthreadex来初始化C执行时库。而相同地,假设线程被强制终止(TerminateThread),由于  TerminateThread是不会去管 C执行时库的,从而,导致部分和引用计数相关的C执行时数据的内存释放出现故障。最典型的特征是,使用STL库的静态变量
内存回收将出错,从而导致进程退出时误报异常。

此外,假设AfxBeginThread频繁进行回收和分配线程,假设不严格操作,也会导致崩溃。

VC6中,应该严格控制STL库的使用,避免MFC库和STL库并存,否则,会有非常多问题。

原因:

AfxBeginThread在内部直接调用了CreateThread创建线程而不是c语言下推荐的beginthreadex函数,而这两个函数是有差别的,主要是c执行库的历史遗留问题造成的。

在多线程环境中存在问题的C/C++执行期库变量和函数包含errno、_doserrno、strtok、_wcstok、strerror、_strerror、tmpnam、tmpfile、asctime、_wasctime、gmtime、_ecvt和_fcvt等。

若要使多线程C/C++程序可以正确地执行,必须创建一个数据结构,并将它与使用C/C++执行期库函数的每一个线程关联起来。当你调用C / C + +执行期库时,这些函数必须知道查看调用线程的数据块,这样就不会对别的线程产生不良影响。

那么系统是否知道在创建新线程时分配该数据块呢?回答是它不知道。系统根本不知道你得到的应用程序是用C/C++编写的。也不知道你调用函数的线程本身是不安全的。问题在于你必须正确地进行全部的操作。

若要创建一个新线程。绝对不要调用操作系统的CreateThread函数。必须调用C/C++执行期库函数_beginthreadex。

以下是关于_beginthreadex的一些要点:

      每一个线程均获得由C/C++执行期库的堆栈分配的自己的tiddata内存结构。(tiddata结构位于Mtdll.h文件里的Visual C++源码中)。传递给_beginthreadex的线程函数的地址保存在tiddata内存块中。

传递给该函数的參数也保存在该数据块中。

_beginthreadex确实从内部调用CreateThread,由于这是操作系统了解怎样创建新线程的唯一方法。###能够看出调用_beginthreadex时分配了额外的内存空间。



    假设调用CreateThread,而不是调用C / C + +执行期库的_beginthreadex来创建新线程,将会发生什么情况。当一个线程调用要求tiddata结构的C / C + +执行期库函数时,将会发生以下的一些情况(大多数C / C + +执行期库函数都是线程安全函数,不须要该结构)。



先。 C / C + +执行期库函数试图(通过调用TlsGetValue)获取线程的数据块的地址。

假设返回

NULL作为tiddata块的地址。调用线程就不拥有与该地址相关的tiddata块。这时,C / C + +执行期库函数就在现场为调用线程分配一个tiddata块,并对它进行初始化。然后该tiddata块(通过TlsSetValue)与线程相关联。

###_beginthreadex相相应的推出函数是_endthreadex,这个函数会释放tiddata的内容。

---------------------------

    假设你採用CreateThread创建线程。而你没有使用上面所提到的那些特殊执行期库的话,也是不会出现故障的。假设一定要用那些执行库的话就最好调用_beginthreadex 这个api来创建线程,否则tiddata数据块就无法撤销,引起内存泄漏。

你能够參照_beginthreadex源码来进行理解。

引申阅读:

关于_beginthreadex和CreateThread的差别


MFC多线程内存泄漏问题&解决方法的更多相关文章

  1. 上Mysql com.mysql.jdbc.StatementImpl$CancelTask内存泄漏问题和解决方法

    近来在负责公司短信网关的维护及建设,随着公司业务发展对短信依赖越来越严重了,短信每天发送量也比曾经每天40多w发送量暴增到每天达到200w发送量.由于是採用Java做发送底层,压力递增情况下不可避免的 ...

  2. Android 内存泄漏分析与解决方法

    在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...

  3. 使用HandyJSON导致的内存泄漏问题相关解决方法

    在移动开发中,与服务器打交道是不可避免的,从服务器拿到的接口数据最终都会被我们解析成模型,现在比较常见的数据传输格式是json格式,对json格式的解析可以使用原生的解析方式,也可以使用第三方的,我们 ...

  4. Android开发之漫漫长途 番外篇——内存泄漏分析与解决

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  5. Android开发 |常见的内存泄漏问题及解决办法

    在Android开发中,内存泄漏是比较常见的问题,有过一些Android编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢?内存泄漏又有什么影响呢? 在Android程序开发中,当一个对象已经不需要 ...

  6. 5个Android开发中比较常见的内存泄漏问题及解决办法

    android中一个对象已经不需要了,但是其他对象还持有他的引用,导致他不能回收,导致这个对象暂存在内存中,这样内存泄漏就出现了.   内存泄漏出现多了,会是应用占用过多的没存,当占用的内存超过了系统 ...

  7. Linux系统内存占用90%以上——解决方法

    Linux系统内存占用90%以上--解决方法   首先要明确一个问题:Linux系统内存占用90%以上,是否属于正常范围?网上有详细的解释,这属于正常现象~~~    www.2cto.com   L ...

  8. 内存泄漏之malloc替换方法

    //内存泄漏之malloc替换方法 //内存泄漏之malloc替换方法#include "stdio.h"#include "stdlib.h" /*文件路径名 ...

  9. Java虚拟机系列(三)---内存溢出情况及解决方法

    因为Java虚拟机内存有堆内存.方法区.虚拟机栈.本地方法栈和程序计数器五部分组成,其中程序计数器是唯一一块不会发生内存溢出异常的内存区,所以只有四类内存区可能发生内存溢出异常,其中虚拟机栈和本地方法 ...

随机推荐

  1. cocos2dx 编写shader 遇到 溢出问题

    在 编程语言中,不论什么 数据类型 都有 各种 的 局限,无法 表示 现实世界中的 不论什么 情况. 比如 int ,char 会 溢出,float 会 有 溢出 以及 精度 不准确的 情况. 所以 ...

  2. OutputCache各参数的说明

    OutputCache各参数的说明 Duration 缓存时间,以秒为单位,这个除非你的Location=None,可以不添加此属性,其余时候都是必须的. Location Location当被设置为 ...

  3. tabbar加小红点

    原文   http://blog.csdn.net/u013531246/article/details/44460115 #import <UIKit/UIKit.h> @interfa ...

  4. oc基础 不可变字符串的创建和使用

    oc基础  不可变字符串的创建和使用 简介:下面都是字符串基本用法. 1.字符串的创建 //创建oc常量字符串 NSString *str=@"hello world!"; NSL ...

  5. javascript延迟加载及异步(defer和async)

    一直以来写代码的时候的常用习惯就是吧所有的js文件直接加载在文档的head标签里面,在写js文件的时候有时候获取一些文件对象的时候为空对象,这是由于文档结构还没有加载完,但是js文件已经加载完.也就是 ...

  6. poi HSSFRichTextString 对cell中的每一段文字设置字体

    HSSFRichTextString ts= new HSSFRichTextString(" 经审核,我司已同意其出库申请.请你部按规定将托管银行承兑汇票办理出库." + &qu ...

  7. git的使用与积累

    之前对git可以说是一无所知,不过现在做工程要用到,于是就花点时间找了一些资料,本文也只是各种git学习资料的集合,权当是学习笔记吧 一:git的安装与配置 首先,git其实一般在linux环境下都是 ...

  8. im2uint8函数分析

    环境:Win7 64位 + Matlab R2010a 本次分析的函数为im2uint8,这个函数在图像处理中要用到,主要把图像数据类转换到uint8 uint8函数有效的输入的图像数据类为:logi ...

  9. PHP APC缓存配置、使用详解

    一.APC缓存简介 APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”.它为我们提供了缓存和优化PHP的中间代码的框架. APC的缓存分两部分:系统缓存和用户数据缓 ...

  10. oracle中anyData数据类型的使用实例

    ---创建waterfallcreate or replace type waterfall is object(name varchar2(30),height number); --创建river ...