关于C\C++运行时库的多线程版本的工作记录
时间:2011-05-18 来源:大文
这段时间在做一个CS模式的项目,服务端运行在linux/windows平台下,使用C语言;客户端运行在windows下,使用MFC开发;开发工具为VC++6.0企业版。。
在开发服务端时,由于是使用C语言,所以经常使用malloc,free等C语言函数;在开发起初阶段,由于只是开发基础模块和基本的功能组件,所以不牵涉到多线程的开发。
在开发过程中,团队的每个成员都就自己的模块编写测试用例,测试用例主要是让模块的功能流程跑一遍并确保正常。
前期基本框架搭好之后,后面主要就功能业务进行开发,其中肯定要使用到多线程技术。。。在每个线程中肯定会调用malloc 和free等函数;
开发一个模块之后,如果可以联调的话,团队成员即配合进行联合调试。。在调试的过程,有时会出现malloc异常和free异常问题。。。。。
针对malloc异常,一直找不到原因,针对free异常,如果是重复释放等原因,会导致异常。。。
因此后来又写了一个内存监测模块,可以输出内存申请的地址,大小,文件名和行号等信息,同时也可以看出内存释放的信息,并且就内存申请和内存释放进行关联,从而可以查看出内存的情况等。。
但是针对malloc异常情况,一直找不到原因,因为以前是做C++开发的,基本上没用到过malloc函数,也不知道malloc会异常等。。后来就去网上查查资料,有的说是内存不足,我在本地测试时,循环申请内存都不是问题,因此不是内存不足的原因。。
后来就和团队成员进行商量,考虑到了多线程原因引起的,但是没有确凿证据,不知malloc等函数是线程安全还是线程不安全的。。于是后来就对malloc和free函数进行了加锁操作。。运行几天,并没有出现异常。。。
至此,这个问题也基本解决了,但是仔细想一想,别人在开发C语言程序时,如果是多线程时,都要对C函数进行加锁操作吗?
最后,在成员们和老大们开会时,老大们一针见血的对该问题提出了意见:在VC工程中,设置其C Runtime 版本为多线程版本即可,原来如此啊。。。
设置如下图所示(在工程设置里,VC6.0默认是单线程的。。。无语中。。):
下班回来后,特定查了下资料和书籍,心中的疑惑也就解开了,原文如下:
什么是C Runtime 函数库的多线程版本
当C runtime 函数库于1970s 年代产生出来时,PC 的内存容量还很小,多任务是
个新奇观念,更别提什么多执行线程了。因此以当时产品为基础所演化的C runtime 函
数库在多线程(multithreaded)的表现上有严重问题,无法被多线程程序使用。
利用各种同步机制(synchronous mechanism)如critical section、mutex、semaphore、
event,可以重新开发一套支持多执行线程的runtime 函数库。问题是,加上这样的能
力,可能导至程序代码大小和执行效率都遭受不良波及-- 即使你只激活了一个执行
线程。
Visual C++ 的折衷方案是提供两种版本的C runtime 函数库。一种版本给单线程程序
使用,一种版本给多线程程序使用。多线程版本的重大改变是,第一,变量如errno 者
现在变成每个执行线程各拥有一个。第二,多线程版中的数据结构以同步机制加以保护。
Visual C++ 一共有六个C runtime 函数库产品供你选择:
Single-Threaded(static) libc.lib 898,826
Multithreaded(static) libcmt.lib 951,142
Multithreaded DLL msvcrt.lib 5,510,000
Debug Single-Threaded(static) libcd.lib 2,374,542
Debug Multithreaded(static)libcmtd.lib 2,949,190
Debug Multithreaded DLL msvcrtd.lib 803,418
Visual C++ 编译器提供下列选项,让我们决定使用哪一个C runtime 函数库:
/ML Single-Threaded(static)
/MT Multithreaded(static)
/MD Multithreaded DLL(dynamic import library)
/MLd Debug Single-Threaded(static)
/MTd Debug Multithreaded(static)
/MDd Debug Multithreaded DLL(dynamic import library)