GetLastError()问题

本文探讨了Windows API中使用内存映射文件时遇到的一个陷阱:OpenFileMapping函数的成功与GetLastError()值之间的关系。通过实验验证了OpenFileMapping成功后并不会重置错误代码,提出了解决方案,并附带讨论了句柄与指针的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现象:

	HANDLE handle = nullptr;

	BOOL bCreate = FALSE;

	handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, strFileID);

	if (handle && NO_ERROR == GetLastError())
		bCreate = TRUE;


  今天遇到一个奇怪的现象,OpenFileMapping后handle有值但GetLastError() = 2,百思不得其解。

发现问题:  

  调试过程中发现$err,hr显示在OpenFileMapping之前就一直是2,猜测OpenFileMapping成功不会更新GetLastError()的值,于是:

	SetLastError(ERROR_FILE_NOT_FOUND);

	HANDLE handle1 = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 0x1000, _T("123"));	//$err,hr = S_OK

	LPVOID pVoid1 = MapViewOfFile(handle1, FILE_MAP_ALL_ACCESS, 0, 0, 0);

	SetLastError(ERROR_FILE_NOT_FOUND);

	HANDLE handle2 = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, _T("123"));	//$err,hr = ERROR_FILE_NOT_FOUND

	LPVOID pVoid2 = MapViewOfFile(handle2, FILE_MAP_ALL_ACCESS, 0, 0, 0);

  确定了刚才的猜测。

解决方法:

	DWORD SafeGetLastError()
	{
		DWORD dwError = GetLastError();
		SetLastError(NO_ERROR);
		return dwError;
	}


  1.首先想到的是定义如上函数,获取之后马上将值重置,但随即否定,不可能在每个会更新GetLastError()值的地方都调用该函数。

  2.去掉GetLastError的返回值判断,但可能发生其它意外情况,我不确定到底会不会有问题,有风险。

  3.在调用OpenFileMapping之前SetLastError(NO_ERROR),不足之处在于每次调用之前都需要加,可以通过增加SafeOpenFileMapping函数解决,好在整个程序就三处,也就懒得加了。

题外:

  但是又引出了另外的疑问:

  handle1 = 0x0000010c;

  handle2 = 0x00000108;

  pVoid1 = 0x00320000;

  pVoid2 = 0x00330000;

  我们知道句柄是标识一个对象的ID,操作系统内核对象的句柄在不同进程间的值可以不相同,每个进程维护着自己的句柄映射表,但相同进程获得的值应该相同。虽然指针也是物理内存的映射地址,不同的指针可以指向同一块物理内存,但32位系统指针为8位十六进制的值,也就是一个进程可以访问的内存大小为16的8次方 = 4294967296B = 4096MB = 4G,如果两个指针指向了同一块内存就说明该程序在释放这个指针之前可以访问的内存大小就小了。

  进行如下测试:

*(int*)pVoid1 = 4;


  查看内存发现两个地址中的值都被改了,可以正常使用共享内存。

  从代码级别上考虑,两次Create就要有两次Release,如果是相同的值,可以通过计数器实现,委实不知道为什么这么设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值