HeapAlloc()失败后调用GetLastError()可靠吗?

问题描述 投票:0回答:1

我最近在查看一些代码,在

GetLastError()
失败后确实调用了
HeapAlloc()
。但是,根据 HeapAlloc 函数 MSDN 文档:

如果函数失败,它不会调用SetLastError。应用程序无法调用 GetLastError 来获取扩展错误信息。

互联网上充斥着在

GetLastError()
失败后调用
HeapAlloc()
的代码片段,我认为大多数程序员(包括我自己)都被编程为在 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 失败:没有足够的可用内存。

问题

为什么

GetLastError()
看起来有效?难道这只是运气,所以大家应该避免调用它,因为依靠
GetLastError()
获取详细的错误信息可能不可靠?

更新

HeapAlloc()
的官方文档注释:

如果函数失败,它不会调用SetLastError。应用程序无法调用 GetLastError 来获取扩展错误信息。

但是,从下面的评论来看,

HeapAlloc()
的内部实现可能会与TEB中的
LastErrorValue
交互,但没有为外部开发人员提供文档,并且依赖于操作系统。

这是

HeapAlloc
在 TEB 中使用
LastErrorValue
8 (0x8) 更新
ERROR_NOT_ENOUGH_MEMORY
的快照。

总而言之,我会坚持使用官方文档而不是调用

GetLastError()
。谢谢。

windows winapi
1个回答
0
投票

为了测试,[...]

您无法“测试”合同是否有效。

合同是。

前置条件和后置条件的组合称为契约实施有权放宽其先决条件并加强其后置条件。当这种情况发生时,它被称为“实施细节”。 实施细节不属于合同的一部分。

如果

HeapAlloc

 的文档指出

应用程序无法调用
GetLastError

来获取扩展错误信息。


那么这就是与其后置条件相关的契约。当
GetLastError

返回

HeapAlloc
时,不要调用
NULL
    

© www.soinside.com 2019 - 2024. All rights reserved.