首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

FreeLibrary的一个小疑点

2012-01-23 
FreeLibrary的一个小问题如下面代码所示,为什么使用FreeLibrary后,这个进程还能使用这个模块的信息呢?HINS

FreeLibrary的一个小问题
如下面代码所示,为什么   使用FreeLibrary后,这个进程还能使用这个模块的信息呢?
HINSTANCE   hUser   =   LoadLibrary( "user32.dll ");
  if   (!   hUser)
  {
    cout < < "Can   not   load   library\n ";
    return   0;
  }
  data.dwMessageBox   =   (DWORD)GetProcAddress(hUser,   "MessageBoxA ");
  FreeLibrary(hUser);
........
  if   (!   WriteProcessMemory(hProcess,   pData,   &data,   sizeof   (MyData),   0))
    return   0;

[解决办法]

基于加载的性能考虑,引用计数到0之后Windows也不会马上释放的。不过你这么用的话会有不可意料的行为,还是用完之后再Free比较好。
[解决办法]
哦, MessageBoxA 的地址啊
在windows平台上的程序的MessageBoxA函数的虚拟内存地址(入口地址)基本上是固定的(一致的),但是也有可能会出现不一致的情况,不一致的时候这样访问就会出现错误

你可以这样试一下
自己做个DLL(假设叫C),export一个函数Test,创建2个可执行程序 A 和 B,启动A(A不要加载C),启动B,B加载C,然后把B进程的进程空间中的C的Test的入口地址通过远程线程方式插进进程A的空间,在进程A中访问这个地址,必然报错

[解决办法]
不太赞同楼上的回答
系统的确会在加载PE时发现基地址被占用的话,会进行重定位
但是不能就说“一个DLL在不同进程中的虚拟地址是不同的“
对此,我做了如下简单测试,说明在下述情况下一个DLL在不同的进程中的虚拟地址是相同的

测试DLL代码( TestAddr.cpp)
#include <stdio.h>
#include <windows.h>

extern "C " __declspec(dllexport) int Test( void ) {
return( 111 );
}


测试进程代码(TestA.cpp)
#include <windows.h>
#include <tlhelp32.h>

typedef int __declspec(dllimport) (* PTEST)( void );

long GetModuleBaseAddress( const char * lpName ) {
DWORD retVal = 0;
DWORD myID = GetCurrentProcessId();
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, myID );
if( hSnap ) {
MODULEENTRY32 modEntry = { 0 };
modEntry.dwSize = sizeof( MODULEENTRY32 );
if( Module32First( hSnap, &modEntry ) ) {
printf( "Main Process Base Address is: 0x%08X\n ", (DWORD)modEntry.modBaseAddr );

while( Module32Next( hSnap, &modEntry ) ) {
if( ! stricmp( modEntry.szModule, lpName ) ) {
retVal = (DWORD)modEntry.modBaseAddr;
}
}
}
CloseHandle( hSnap );
}

return( retVal );
}

int main( void ) {
HMODULE hTest = LoadLibrary( "TestAddr " );

if( hTest ) {
PTEST pf = (PTEST)GetProcAddress( hTest, "Test " );
if( pf )
printf( "Function returns: %d\n ", pf() );

printf( "Module Handle is: 0x%08X\n ", hTest );
}

printf( "Module Base Address is: 0x%08X\n ", GetModuleBaseAddress( "TestAddr.dll " ) );

getchar();

return( 0 );
}

建立两个目录 A 和 B,把 TestA.exe 和 TestAddr.dll 都复制到A和B2个目录中
在A目录中运行TestA.exe,运行到getchar()会等待输入(这时候TestAddr.dll是加载的),再在B目录中运行TestA.exe,运行到getchar()会等待输入(这时候TestAddr.dll也是加载的),2个窗口的输出一致,如下:
Function returns: 111
Module Handle is: 0x10000000
Main Process Base Address is: 0x00400000
Module Base Address is: 0x10000000

如果我说的不对或者测试方法错误,还望不吝指正

热点排行