今天编程遇到一个问题:
以下这个函数的定义:
std::wstring QueryIni::GetValue(const int iKey)
{
wchar_t sDes[MAX_PATH + 1] = { 0 };
QueryIni::_GetInstance()->_GetValue(iKey, sDes, MAX_PATH);
return sDes;
}
为什么要放在头文件中,而不是像平常一样,声明写在头文件,定义写在cpp文件呢?
由于对DLL,静态链接库等概念的浅薄理解,引用静态链接和动态链接的区别
如下总结到的知识点:
lib有静态lib和DLL之分。
静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序
DLL相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时候需要相应的dll文件支持
还有一个知识点是:跨模块内存管理的陷阱
我对此一个比较关键的理解是,不要在模块A中申请内存,而在模块B中申请释放。
看到函数的定义,返回一个sDes,如下述代码:
std::wstring str = GetValue(iKey);
那么先会在函数内部生成一个std::wstring类的strTemp临时变量,作为返回值返回给函数外部,那么这个std::wstring临时变量就要在外部释放。
结合以上2个知识点,也就是说如果我写的上述类使用动态lib, 那么实现的cpp文件和调用GetValue的文件则不属于同一个模块。如果该GetValue函数写在实现文件中,那么就会导致同样的一片内存在不同的模块中申请和释放。所以,应该把这个函数定义写到头文件中。
这里也引用一个《windows核心编程》的19-DLL基础中提到的一个错误代码,以让自己加深印象:
PVOID DLLFunc(){
//Allocate block from DLL's C/C++ run-time heap
return (malloc(100));
}
VOID EXEFunc()
{
PVOID pv = DLLFunc();
//Access the sortage pointed by pv
//Assume that pv is in EXE's C/C++ run-time heap
free(pv);
}