diff --git "a/Windows\347\274\226\347\250\213 MD(d)\343\200\201MT(d)\347\274\226\350\257\221\351\200\211\351\241\271\347\232\204\345\214\272\345\210\253.txt" "b/Windows\347\274\226\347\250\213 MD(d)\343\200\201MT(d)\347\274\226\350\257\221\351\200\211\351\241\271\347\232\204\345\214\272\345\210\253.txt" new file mode 100644 index 0000000..5c0cd37 --- /dev/null +++ "b/Windows\347\274\226\347\250\213 MD(d)\343\200\201MT(d)\347\274\226\350\257\221\351\200\211\351\241\271\347\232\204\345\214\272\345\210\253.txt" @@ -0,0 +1,119 @@ +Windows编程 MD(d)、MT(d)编译选项的区别 +标签: windows编程多线程dllgeneration +2012-05-09 16:27 9201人阅读 评论(0) 收藏 举报 + 分类: windows编程(20) +目录(?)[+] +1、编译选项的位置 +以VS2005为例,这样子打开: + +1) 打开项目的Property Pages对话框 + +2) 点击左侧C/C++节 + +3) 点击Code Generation节 + +4) 右侧第六行Runtime Library项目 + +2、各个设置选项代表的含义 +编译选项 + +包含 + +静态链接的lib + +说明 + +/MD + +_MT、_DLL + +MSVCRT.lib + +多线程、Release、DLL版本的运行时库 ---只能用于Release版本 + +/MDd + +_DEBUG、_MT、_DLL + +MSVCRTD.lib + +多线程、Debug、DLL版本的运行时库 ----只能用于Debug版本 + +/MT + +_MT + +LIBCMT.lib + +多线程、Release版本的运行时库 + +/MTd + +_DEBUG、_MT + +LIBCMTD.lib + +多线程、Debug版本的运行时库 + + + +简单的说: + +(1)/MD,表示运行时库由操作系统提供一个DLL,程序里不集成。 + +(2)/MT,表示运行时库由程序集成,程序不再需要操作系统提供运行时库DLL。 + + + +/MT是"multithread, static version" 意思是多线程静态的版本,定义了它后,编译器把LIBCMT.lib安置到OBJ文件中,让链接器使用LIBCMT.lib 处理外部符号。 +/MD是"multithread- and DLL-specific version",意思是多线程DLL版本,定义了它后,编译器把MSVCRT.lib安置到OBJ文件中,它连接到DLL的方式是静态链接,实际上工作的库是MSVCR80.DLL。 +即: +静态运行时库:LIBCMT.lib +动态运行时库:MSVCRT.lib +MSVCR80.DLL +二、/MD、/MT的选择 + 1、为什么选择/MD,不选/MT? + (1)程序就不需要静态链接运行时库,可以减小软件的大小; + + (2)所有的模块都采用/MD,使用的是同一个堆,不存在A堆申请,B堆释放的问题。 + + 2、为什么选择/MT,不选择/MD? + (1)有些系统可能没有程序所需要版本的运行时库,程序必须把运行时库静态链接上。 + + 3、多个模块,必须选择相同类型的运行时库,不要混合使用。 + + + + +三、选择/MT需要解决的堆空间释放问题 + 不同的模块各自有一份C运行时库代码,各个C运行库会有各自的堆,导致了各个模块会有各自的堆。如果在A堆中申请空间,到B堆中释放就会有崩溃,在模块A申请的空间,必须在模块A中释放。 + + 附件(下载地址:http://files.cnblogs.com/cswuyg/Test_MD_and_MT.rar)的DLL以及DLLUser代码,以STL的string为例,通过修改编译选项验证了这个问题。(string在赋值的时候需要释放掉原来的空间,然后再申请新的空间存储新的内容。) + + + +四、参考资料 +1、微软关于MT、MD等的详细介绍 + +http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx + +2、不要出现A模块申请,B模块释放的情况 + +http://www.cnblogs.com/minggoddess/archive/2010/12/15/1907179.html + +3、运行时库有哪些版本 + +http://www.cppblog.com/MichaelLiu/articles/10607.html + +4、CSDN上关于堆空间释放的讨论 + +http://topic.csdn.net/t/20010112/09/57983.html + +http://topic.csdn.net/t/20031009/17/2338051.html + +http://topic.csdn.net/u/20090502/00/bf1602e3-ddf5-49b0-af81-8a23383f9ddc.html + +http://blog.csdn.net/blz_wowar/article/details/2176536 + +5、不同模块不同的堆 + +http://www.cnblogs.com/WengYB/archive/2011/08/18/2144727.htm \ No newline at end of file diff --git a/hzInFile.cpp b/hzInFile.cpp new file mode 100644 index 0000000..d108795 --- /dev/null +++ b/hzInFile.cpp @@ -0,0 +1,41 @@ +void hzInFile (CString FileName) +{ + FILE *in; + unsigned char c1, c2; + int id; + in=fopen((const char *)FileName, "rb"); + if(in==NULL) + { + AfxMessageBox("无法打开输入文件!"); + return; + } + while (!feof (in)) + { + c1=(unsigned char ) fgetc(in); // 转换为无符号字符 + if(c1<128) + continue; // 不处理单字节西文字符 + if(c1<176) + { + c2=fgetc(in); + continue; + } // 也不处理非汉字字符,但要多读一个字节 + c2=(unsigned char ) fgetc(in); // 读入汉字的第二个字节 + id=HZ_ID(c1,c2); // 计算该汉字的下标 + HZFreq[id]++; // 给该汉字的频度加1 + } + fclose(in); + return; +} +void OnSingleHz() +{ + // 单字字频统计 + for(int i=0; i0) + fprintf(outFile, "%c%c\t%d\n", id/94+176, id%94+161, HZFreq[id]); + fclose(outFile); + return; +} \ No newline at end of file diff --git "a/\345\234\250VS\344\270\255\345\210\233\345\273\272\345\222\214\344\275\277\347\224\250DLL\345\212\250\346\200\201\351\223\276\346\216\245\345\272\223.txt" "b/\345\234\250VS\344\270\255\345\210\233\345\273\272\345\222\214\344\275\277\347\224\250DLL\345\212\250\346\200\201\351\223\276\346\216\245\345\272\223.txt" new file mode 100644 index 0000000..0a0d752 --- /dev/null +++ "b/\345\234\250VS\344\270\255\345\210\233\345\273\272\345\222\214\344\275\277\347\224\250DLL\345\212\250\346\200\201\351\223\276\346\216\245\345\272\223.txt" @@ -0,0 +1,105 @@ +在VS中创建和使用DLL动态链接库 + +VS中使用动态链接库较GCC略微复杂 + +在VS中新建工程时建立dll工程 +在dll工程的头文件中加入如下宏 + +#ifdef DLL_IMPLEMENT_ +#define DLL_APL __declspec(dllexport) +#else +#define DLL_API __declspec(dllimport) +#endif +__declspec(dllimport)和__declspec(dllexport)声明了某一对象的导入/导出属性 + +在dll的实现文件头部使用宏将其声明为dll内部的实现 + +#define DLL_IMPLEMENT_ +如使用dll的工程和dll工程同属一个解决方案,在解决方案的属性中设置好工程的依赖关系,在使用dll的工程的属性中设置好头文件和库文件的路径,即可直接编译运行,需要注意的是,VS编译使用dll的程序时,依然需要该dll对应的lib文件,和gcc直接可以连接动态库有所不同 +可以将一个dll的相关内容包含在一个命名空间里,由于命名空间的定义可以不连续,这样也不会对实现和接口的分离造成什么麻烦 + +程序例子 + +DLL头文件: DLLtest.h + +#ifndef _TEST_H_ +#define _TEST_H_ + +#ifdef DLL_IMPLEMENT_ +#define DLL_API __declspec(dllexport) +#else +#define DLL_API __declspec(dllimport) +#endif + +namespace dll +{ + int DLL_API add(const int &a, const int &b); + int DLL_API sub(const int &a, const int &b); + int DLL_API mul(const int &a, const int &b); + int DLL_API div(const int &a, const int &b); +} + +#endif +DLL实现文件:DLLtest.cpp + +#define DLL_IMPLEMENT_ +#include "test.h" + +namespace dll +{ + int add(const int &a, const int &b) + { + return a + b; + } + + int sub(const int &a, const int &b) + { + return a - b; + } + + int mul(const int &a, const int &b) + { + return a * b; + } + + int div(const int &a, const int &b) + { + return a / b; + } +} +应用程序:entry.cpp + +#include "test.h" +#include + +#pragma comment(lib, "DLLtest.lib") + +using namespace std; +using namespace dll; + +int main() +{ + int a, b; + char c; + while( cin >> a >> c >> b ) + { + switch( c ) + { + case '+': + cout << add(a, b) << endl; + break; + case '-': + cout << sub(a, b) << endl; + break; + case '*': + cout << mul(a, b) << endl; + break; + case '/': + cout << dll:: div(a, b) << endl; + break; + default: + cout << '\"' << a << c << b << '\"' << "isn't a valid expression." << endl; + } + } +} +Written with StackEdit. \ No newline at end of file