静态库、动态库

纯 lib 文件链接后已经不存在了,链接的时候连接器直接把 lib 中的函数代码拷贝到对应的 exe 或 dll 中. 所以运行的时候只有 exe, dll 这些模块, 没有 lib 的东西.
内存分配最终会调用 HeapAlloc 这个 API 来分配内存,这个函数的参数需要一个堆的句柄. 这个堆句柄是在 dll 或 exe 进入 main 之前由 CRT 库来初始化的。所以每个模块都有自己独立的堆句柄,当分配和释放内存所传递的堆句柄不相同时,DEBUG 版本就会提示一个错误来提醒程序员这个问题。
下面再看静态链接和动态链接 CRT 库的区别:
静态链接时,CRT 库的内存分配代码是被拷贝到了最终执行体中(dll 或 exe), 这样每次调用 new 或 delete 时使用的是这个模块的堆句柄,如果在一个模块中分配的内存,在另外一个模块中释放就会出现问题.
动态链接时, CRT 库的代码放在自己的 dll 中, 其它使用动态链接的模块要分配或释放内存都是调用 CRT 的 dll 模块来完成的.所以所有的分配和释放都在 CRT DLL 这同一个模块中,使用的就是同一个句柄,于是就没有错误了。
http://bbs.csdn.net/topics/360251437

静态库和动态库里的全局变量(或类的静态成员变量)共享和独立的问题
本文将要讨论的内容实际上包含2个问题:
1. 工程中包含静态库A,动态库B,可执行程序C。C依赖于A和B,而B依赖于A。在A中定义有全局变量X(或类的静态成员变量),则在动态库B中访问的X,与可执行程序C中访问的X是同一个变量还是两个不同的变量?
答案:是两个不同的变量。

测试代码如下:
[cpp] view plain copy
//A中定义变量g_nValue(A.cpp):
int g_nValue = 0;

//B代码 (B.cpp):
extern int g_nValue;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

void SetValue(int value)
{
g_nValue = value;
}

//C代码 (TestDlgDlg.cpp):
extern void SetValue(int);
extern int g_nValue;

void CTestDlgDlg::OnButton1()
{
CString strMessage;

SetValue(23);  


strMessage.Format("g_nValue=%d\n", g_nValue);  
AfxMessageBox(strMessage);  

}

执行结果: g_nValue = 0,SetValue没有起作用,因为此时,在B和C中有两个g_nValue的拷贝,SetValue(23)修改的只是B中的拷贝,不会影响C中的值。
静态库就是这样,与B和C它们自己分别定义g_nValue效果是一样的,因为静态库在编译阶段就把A的代码链接到B和C中,像它们自己的代码一样。

  1. 工程中包含动态库A,动态库B,可执行程序C。C依赖于A和B,而B依赖于A。在A中定义有全局变量X(或类的静态成员变量),则在动态库B中访问的X,与可执行程序C中访问的X是同一个变量还是两个不同的变量?(注:所有库都在同一进程中使用)
    答案:是共享同一个变量。即:在A是动态库的这种情况下,B和C访问到的X是同一变量。

测试代码如下:
[cpp] view plain copy
//A中定义变量g_nValue(A.cpp):
__declspec(dllexport) int g_nValue = 0;

//B代码 (B.cpp):
__declspec(dllimport) int g_nValue;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

void SetValue(int value)
{
g_nValue = value;
}

//C代码 (TestDlgDlg.cpp):
extern void SetValue(int);
__declspec(dllimport) int g_nValue;

void CTestDlgDlg::OnButton1()
{
CString strMessage;

SetValue(23);  


strMessage.Format("g_nValue=%d\n", g_nValue);  
AfxMessageBox(strMessage);  

}
执行结果: g_nValue = 23,证明SetValue起了作用,修改g_nValue为23,在A是动态库时,这个变量在B和C中指向同一实例,就是A中定义的g_nValue。
从这个测试中也可以看到__declspec(dllexport),__declspec(dllimport)这两个关键字的作用,可以从动态库中导出和导入变量。
http://blog.csdn.net/while0/article/details/8136325

小心两个共享库共用同一个静态库__linux版
http://blog.csdn.net/imxiangzi/article/details/45872065

Linux 静态库与共享库的使用
http://blog.csdn.net/imxiangzi/article/details/45872111

C++又一坑:动态链接库中的全局变量
http://blog.csdn.net/imxiangzi/article/details/45872025

C++静态库与动态库
http://blog.jobbole.com/86852/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值