??xml version="1.0" encoding="utf-8" standalone="yes"?>免费福利在线视频,中文综合在线观看,电影一区二区三区久久免费观看http://www.aygfsteel.com/thisliy/category/42849.htmlzh-cnMon, 30 Nov 2009 12:12:42 GMTMon, 30 Nov 2009 12:12:42 GMT60DllMain详解http://www.aygfsteel.com/thisliy/archive/2009/11/30/304261.htmlliyangliyangMon, 30 Nov 2009 07:25:00 GMThttp://www.aygfsteel.com/thisliy/archive/2009/11/30/304261.htmlhttp://www.aygfsteel.com/thisliy/comments/304261.htmlhttp://www.aygfsteel.com/thisliy/archive/2009/11/30/304261.html#Feedback0http://www.aygfsteel.com/thisliy/comments/commentRss/304261.htmlhttp://www.aygfsteel.com/thisliy/services/trackbacks/304261.html

DllMain详解

1   DLL的进?退出函?/p>

1.1 DllMain?/p>

跟exe有个main或者WinMain入口函数一PDLL也有一个入口函敎ͼ是DllMain。以“DllMain”为关键字Q来看看MSDN帮助文档怎么介绍q个函数的?/p>

The DllMain function is an optional method of entry into a dynamic-link library (DLL)。(要翻译:(x)对于动态链接库QDllMain是一个可选的入口函数。)q句话很重要Q很多初学者可能都认ؓ(f)一个动态链接库肯定要有 DllMain函数。其实不?dng)像很多仅仅包含资源信息的DLL是没有DllMain函数的?/p>

1.2 何时调用DllMain

       pȝ是在什么时候调用DllMain函数的呢Q静态链接时Q或动态链接时调用LoadLibrary和FreeLibrary都会(x)调用DllMain函数。DllMain的第三个参数fdwReason指明了系l调用Dll的原因,它可能是:

DLL_PROCESS_ATTACH?/font>

DLL_PROCESS_DETACH?/font>

DLL_THREAD_ATTACH

DLL_THREAD_DETACH?/font>

以下从这四种情况来分析系l何时调用了DllMain?nbsp;           

1.2.1 DLL_PROCESS_ATTACH

       大家都知道,一个程序要调用Dll里的函数Q首先要先把DLL文g映射到进E的地址I间。要把一个DLL文g映射到进E的地址I间Q有两种Ҏ(gu)Q静态链接和动态链接的LoadLibrary或者LoadLibraryEx?/p>

       当一个DLL文g被映到q程的地址I间Ӟpȝ调用该DLL的DllMain函数Q传递的fdwReason参数? DLL_PROCESS_ATTACH。这U调用只?x)发生在W一ơ映时。如果同一个进E后来ؓ(f)已经映射q来的DLL再次调用LoadLibrary或? LoadLibraryExQ操作系l只?x)增加DLL的用次敎ͼ它不?x)再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。不? q程用LoadLibrary同一个DLLӞ每个q程的第一ơ映都?x)用DLL_PROCESS_ATTACH调用DLL的DllMain函数?/p>

       可参考DllMainTest的DLL_PROCESS_ATTACH_Test函数?/p>

1.2.2 DLL_PROCESS_DETACH

       当DLL被从q程的地址I间解除映射Ӟpȝ调用了它的DllMainQ传递的fdwReason值是DLL_PROCESS_DETACH。当DLL处理该值时Q它应该执行q程相关的清理工作?/p>

       那么什么时候DLL被从q程的地址I间解除映射呢?两种情况Q?/p>

       ◆FreeLibrary解除DLL映射Q?font color="#ff0000">有几个LoadLibraryQ就要有几个FreeLibraryQ?/p>

       ◆进E结束而解除DLL映射Q在q程l束前还没有解除DLL的映,q程l束后会(x)解除DLL映射。(如果q程的终l是因ؓ(f)调用? TerminateProcessQ系l就不会(x)用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这意味着DLL在进E结束前 没有Z(x)执行M清理工作。)

       注意Q当用DLL_PROCESS_ATTACH调用DLL的DllMain函数Ӟ如果q回FALSEQ说明没有初始化成功Q系l仍?x)用DLL_PROCESS_DETACH调用DLL的DllMain函数。因此,必须保清理那些没有成功初始化的东西?/font>

       可参考DllMainTest的DLL_PROCESS_DETACH_Test函数?/p>

1.2.3 DLL_THREAD_ATTACH

       当进E创ZU程Ӟpȝ查看当前映射到进E地址I间中的所有DLL文g映像Qƈ用值DLL_THREAD_ATTACH调用DLL的DllMain函数?/p>

新创建的U程负责执行q次的DLL的DllMain函数Q只有当所有的DLL都处理完q一通知后,pȝ才允许进E开始执行它的线E函数?/p>

注意跟DLL_PROCESS_ATTACH的区别,我们在前面说q,W? n(n>=2)ơ以后地把DLL映像文g映射到进E的地址I间Ӟ是不再用DLL_PROCESS_ATTACH调用DllMain的。? DLL_THREAD_ATTACH不同Q进E中的每ơ徏立线E,都会(x)用值DLL_THREAD_ATTACH调用DllMain函数Q哪怕是U程中徏? U程也一栗?/p>

1.2.4 DLL_THREAD_DETACH

       如果U程调用了ExitThread来结束线E(U程函数q回Ӟpȝ也会(x)自动调用ExitThreadQ,pȝ查看当前映射到进E空间中的所有DLL? 件映像,q用DLL_THREAD_DETACH来调用DllMain函数Q通知所有的DLLL行线E的清理工作?/p>

       注意Q如果线E的l束是因为系l中的一个线E调用了TerminateThreadQ系l就不会(x)用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数?/p>

1.3 为DllMain换名

在早期的SDK版本中,DllMain是叫做DllEntryPoint。其实有一仉Zh 知的事:(x)一个Dll的入口函数名是可以自己定义的。下面我以VC++6.0Z来演C如何更攏V首先要说明一点,虽然DllMain可以换成其他函数 名,但函数的参数和返回值必dDllMain一栗而且q个函数要ؓ(f)__stdcallcdQDllMain本n也是__stdcallcdQ?/p>

打开VC++菜单Project"Settings"Link tab" Output in the Category boxQ如下图Q在Entry-point symbol中输入要替换DllMain的函数名Q当然这个函数名是你E序中已l实现的函数Q。Entry-point symbol是干么的呢?可以以关键字“Entry-point symbol”搜烦(ch)MSDN帮助文档查看Q搜索时Q打?#8220;仅搜索标?#8221;?x)更快定位?/p>

DllMain详解 - 生活 - 无敌

         按OK后,如果马上~译的话?x)出现如下错误?x)

LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

Debug/Dll.dll : fatal error LNK1120: 1 unresolved externals

打开VC++菜单Project"Settings"C/C++选项卡,如下图,? Project OptionsQ末地方d”/D”Q图中蓝色高亮的地方Q,要注意位|,我试了,要把/D攑ֈ/GZ后面也会(x)链接错误Q我也不懂ؓ(f)什么,^_^。按 OKQ再ơ编译,成功。大家可以自己测试下到底有没有更Ҏ(gu)功,什么,如果试Q打式信息啊?/p>

DllMain详解 - 生活 - 无敌

1.4 DisableThreadLibraryCalls

看帮助就知道它是q么用的Q?/p>

The DisableThreadLibraryCalls function disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the dynamic-link library (DLL) specified by hLibModule. This can reduce the size of the working code set for some applications.

转自:http://blog.csdn.net/benkaoya/archive/2008/06/02/2504781.aspx



liyang 2009-11-30 15:25 发表评论
]]>
typedef的四个用途和两个陷阱http://www.aygfsteel.com/thisliy/archive/2009/11/25/303564.htmlliyangliyangWed, 25 Nov 2009 02:08:00 GMThttp://www.aygfsteel.com/thisliy/archive/2009/11/25/303564.htmlhttp://www.aygfsteel.com/thisliy/comments/303564.htmlhttp://www.aygfsteel.com/thisliy/archive/2009/11/25/303564.html#Feedback0http://www.aygfsteel.com/thisliy/comments/commentRss/303564.htmlhttp://www.aygfsteel.com/thisliy/services/trackbacks/303564.html用途一Q?
定义一U类型的别名Q而不只是单的宏替换。可以用作同时声明指针型的多个对象。比如:(x)
char* pa, pb;  // q多CW合我们的意图,它只声明了一个指向字W变量的指针Q?nbsp;
// 和一个字W变量;
以下则可行:(x)
typedef char* PCHAR;  // 一般用大写
PCHAR pa, pb;        // 可行Q同时声明了两个指向字符变量的指?
虽然Q?
char *pa, *pb;
也可行,但相Ҏ(gu)说没有用typedef的Ş式直观,其在需要大量指针的地方Qtypedef的方式更省事?

用途二Q?
用在旧的C代码中(具体多旧没有查)Q帮助struct。以前的代码中,声明struct新对象时Q必要带上structQ即形式为:(x) struct l构?nbsp;对象名,如:(x)
struct tagPOINT1
{
    int x;
    int y;
};
struct tagPOINT1 p1; 

而在C++中,则可以直接写Q结构名 对象名,卻I(x)
tagPOINT1 p1;

估计某h觉得l常多写一个struct太麻?ch)了Q于是就发明了:(x)
typedef struct tagPOINT
{
    int x;
    int y;
}POINT;

POINT p1; // q样比原来的方式少写了一个structQ比较省事,其在大量用的时?

或许Q在C++中,typedef的这U用途二不是很大Q但是理解了它,Ҏ(gu)握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会(x)遇到较早些年代遗留下来的代码?

用途三Q?
用typedef来定义与q_无关的类型?
比如定义一个叫 REAL 的Q点类型,在目标^C上,让它表示最高精度的cd为:(x)
typedef long double REAL; 
在不支持 long double 的^C上,改ؓ(f)Q?
typedef double REAL; 
在连 double 都不支持的^C上,改ؓ(f)Q?
typedef float REAL; 
也就是说Q当跨^台时Q只要改?nbsp;typedef 本npQ不用对其他源码做Q何修攏V?
标准库就q泛使用了这个技巧,比如size_t?
另外Q因为typedef是定义了一U类型的新别名,不是单的字符串替换,所以它比宏来得E_Q虽然用宏有时也可以完成以上的用途)?

用途四Q?
为复杂的声明定义一个新的简单的别名。方法是Q在原来的声明里逐步用别名替换一部分复杂声明Q如此@环,把带变量名的部分留到最后替换,得到的就是原声明的最化版。D例:(x)

1. 原声明:(x)int *(*a[5])(int, char*);
变量名ؓ(f)aQ直接用一个新别名pFun替换a可以了Q?
typedef int *(*pFun)(int, char*); 
原声明的最化版Q?
pFun a[5]; 

2. 原声明:(x)void (*b[10]) (void (*)());
变量名ؓ(f)bQ先替换双部分括号里的QpFunParam为别名一Q?
typedef void (*pFunParam)();
再替换左边的变量bQpFunx为别名二Q?
typedef void (*pFunx)(pFunParam);
原声明的最化版Q?
pFunx b[10];

3. 原声明:(x)doube(*)() (*e)[9]; 
变量名ؓ(f)eQ先替换左边部分QpFuny为别名一Q?
typedef double(*pFuny)();
再替换右边的变量eQpFunParamy为别名二
typedef pFuny (*pFunParamy)[9];
原声明的最化版Q?
pFunParamy e; 

理解复杂声明可用?#8220;叛_法则”Q从变量名看P先往叻I再往左,到一个圆括号p转阅ȝ方向Q括号内分析完就跛_括号Q还是按先右后左的顺序,如此循环Q直到整个声明分析完。D例:(x)
int (*func)(int *p);
首先扑ֈ变量名funcQ外面有一对圆括号Q而且左边是一?Pq说明func是一个指针;然后跛_q个圆括P先看双Q又遇到圆括Pq说? (*func)是一个函敎ͼ所以func是一个指向这cd数的指针Q即函数指针Q这cd数具有int*cd的Ş参,q回值类型是int?
int (*func[5])(int *);
func双是一个[]q算W,说明func是具?个元素的数组Qfunc的左Ҏ(gu)一?Q说明func的元素是指针Q注意这里的*不是修饰 funcQ而是修饰func[5]的,原因是[]q算W优先?高,func先跟[]l合Q。蟩个括P看右边,又遇到圆括号Q说明func数组? 元素是函数类型的指针Q它指向的函数具有int*cd的Ş参,q回值类型ؓ(f)int?

也可以记?个模式:(x)
type (*)(....)函数指针 
type (*)[]数组指针 
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?

陷阱一Q?
CQtypedef是定义了一U类型的新别名,不同于宏Q它不是单的字符串替换。比如:(x)
先定义:(x)
typedef char* PSTR;
然后Q?
int mystrcmp(const PSTR, const PSTR);

const PSTR实际上相当于const char*吗?不是的,它实际上相当于char* const?
原因在于constl予了整个指针本w以帔R性,也就是Ş成了帔R指针char* const?
单来_(d)C当const和typedef一起出现时Qtypedef不会(x)是简单的字符串替换就行?

陷阱二:(x)
typedef在语法上是一个存储类的关键字Q如auto、extern、mutable、static、register{一PQ虽然它q不真正影响对象的存储特性,如:(x)
typedef static int INT2; //不可?
~译失败,?x)提C?#8220;指定了一个以上的存储c?#8221;?


liyang 2009-11-25 10:08 发表评论
]]>
վ֩ģ壺 | ŷ| ͭϿ| ˮ| ̨| | ɳ| ӻ| ԭ| ˮ| | | | | | ɽ| | | | | ɽ| ɽ| ԭ| | | ʹ| | ˼é| | | ϽϽ| | | | | | ˿| | ˮ| | |