You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:46:08