Nit*_*dur 2 c++ windows winapi
在Windows 7中,VS2012编译器
PostQueuedCompletionStatus(hCompletionPort, 0, (DWORD) pContext, &pOverlap->m_ol);
Run Code Online (Sandbox Code Playgroud)
上面的API调用工作正常.
但是在Windows 10和VS2017编译器上,结构中的成员变量pContext是不可访问的.
当我们改为DWORD时ULONG_PTR,它在Windows 10中运行良好
PostQueuedCompletionStatus(hCompletionPort, 0, (ULONG_PTR) pContext, &pOverlap->m_ol);
Run Code Online (Sandbox Code Playgroud)
这种行为的原因是什么?
很可能新版本不仅在Windows版本中有所不同,而且您还在编译64位,而之前您正在编译32位.
更新:OP已澄清两个版本都是64位,但这很容易解释; 见下文.
DWORD即使在Windows 7/32位上,转换为概念上也是错误的.实际上,API定义需要a ULONG_PTR,这是一个无符号整数类型,足以容纳指针而不会丢失数据.因此,当编译为32位时,它是32位类型,当编译为64位时,它是64位.
相反,你正在指向一个DWORD; DWORD总是一个32位无符号类型,所以当构建32位Windows时一切顺利(指针需要不超过32位才能完好无损地到达另一侧),但在64位Windows上你丢失了指针的前32位.
现在,这甚至可以在64位Windows 7上运行 ; 为什么?
正如注释中所解释的,这个指针来自堆,默认情况下,在Windows 7上,堆开始从64位地址空间的"低"部分提供内存; 因此,除非你消耗大量内存,否则你总是会将前32位的地址设置为零,这样即使前32位被截断,它们也会存活下来.
自Windows 8以来,这一情况发生了变化,因为ASLR(在构建64位可执行文件时默认由链接器启用)随机化了虚拟地址空间中堆的位置,这意味着您将获得具有非零高32位的指针,那些演员要严重致残DWORD.
长话短说:修复你的演员1,一切都会好起来的.此外,将来总是要警惕从一个指向一个完整类型的指针而不是结束_ptr或者_PTR- 你很有可能犯了一个错误.
笔记
void *这些演员才能正常工作,即往返uintptr_t只能保证void *(也许char *?我必须检查标准),所以它应该是(ULONG_PTR)(LPVOID)pContext,如果pContext不是void *已经.然而,这是Win32我很确定它即使没有额外的演员也能保证工作.