HeapAlloc调用失败后调用GetLastError()是否可靠?
HeapAlloc失败后调用GetLastError()的疑问
我最近看到一段代码在HeapAlloc()调用失败后调用了GetLastError(),但根据HeapAlloc的MSDN文档明确说明:
若函数调用失败,不会调用SetLastError,应用程序无法通过GetLastError获取扩展错误信息。
网上有大量类似的代码片段,包括我在内的多数开发者都习惯在API调用失败时调用GetLastError()。为验证这个问题,我写了一段尝试分配最大内存的测试代码:
#include <windows.h> #include <stdio.h> #include <stdint.h> int main() { HANDLE hHeap = GetProcessHeap(); if (hHeap == NULL) { printf("Failed to get the process heap.\n"); return 1; } SetLastError(0); // Clear the last error // Attempt to allocate a very large amount of memory SIZE_T largeSize = SIZE_MAX; LPVOID pMemory = HeapAlloc(hHeap, 0, largeSize); if (pMemory == NULL) { DWORD dwError = GetLastError(); printf("HeapAlloc failed: "); switch (dwError) { case ERROR_NOT_ENOUGH_MEMORY: printf("Not enough memory available.\n"); break; case ERROR_OUTOFMEMORY: printf("Insufficient memory to satisfy the request.\n"); break; default: printf("Error code: %lu\n", dwError); } } else { printf("Memory allocation successful.\n"); HeapFree(hHeap, 0, pMemory); } return 0; }
测试输出为:
HeapAlloc failed: Not enough memory available.
问题
为何GetLastError()看似有效?这只是巧合吗?是否应避免调用它,因为依赖它获取详细错误信息可能不可靠?
更新
HeapAlloc()的官方文档仍明确说明:
若函数调用失败,不会调用SetLastError,应用程序无法通过GetLastError获取扩展错误信息。
但根据反馈,HeapAlloc()的内部实现会更新TEB中的LastErrorValue,但这并未对外公开文档。我编写了示例代码验证HeapAlloc()将TEB中的LastErrorValue更新为ERROR_NOT_ENOUGH_MEMORY(错误码8):
#include <windows.h> #include <stdio.h> #include <stdint.h> #include <intrin.h> typedef struct _MY_TEB { // The TEB is highly stable across Windows versions. uint8_t Padding[0x68]; ULONG LastErrorValue; // ... } MY_TEB; int main() { SetLastError(0); printf("LastErrorValue (TEB): %lu\n", ((MY_TEB*)__readgsqword(0x30))->LastErrorValue); printf("GetLastError (API): %lu\n", GetLastError()); HeapAlloc(GetProcessHeap(), 0, SIZE_MAX); printf("LastErrorValue (TEB): %lu\n", ((MY_TEB*)__readgsqword(0x30))->LastErrorValue); printf("GetLastError (API): %lu\n", GetLastError()); return 0; }
输出结果为:
LastErrorValue (TEB): 0 GetLastError (API): 0 LastErrorValue (TEB): 8 GetLastError (API): 8
综上,我将遵循官方文档,不在HeapAlloc()失败后调用GetLastError()。
内容的提问来源于stack exchange,提问作者vengy
相关产品推荐
相关产品推荐

