RegQueryValueExW returns C 中的访问冲突读取位置异常

RegQueryValueExW returns Access violation reading location exception in C

我有两个用 C 编写的函数,它们应该从 Windows 注册表中读取一些信息。尽管两者使用相同的逻辑,但其中一个会抛出错误。 有效的函数获取一些 CPU 信息。

struct CPUInfo {
    wchar_t model[128];
    DWORD frequency;
};

struct CPUInfo cpuinfo() {
    SYSTEM_INFO siSysInfo;
    HKEY hKey;

    struct CPUInfo cpu = { L"", 0 };

    LONG lRes = RegOpenKeyExW(
        HKEY_LOCAL_MACHINE,
        L"HARDWARE\DESCRIPTION\System\CentralProcessor\0",
        0,
        KEY_READ,
        &hKey
    );
    if (lRes == ERROR_SUCCESS) {
        DWORD dwBufferSize = sizeof(cpu.model);

        ULONG nError = RegQueryValueExW(
            hKey,
            L"ProcessorNameString",
            0,
            NULL,
            (LPBYTE)cpu.model,
            &dwBufferSize
        );
        dwBufferSize = sizeof(DWORD);
        nError = RegQueryValueExW(
            hKey,
            L"~MHz",
            0,
            NULL,
            (LPBYTE)(&cpu.frequency),
            &dwBufferSize
        );
        RegCloseKey(hKey);
    }

    return cpu;
}

此功能有效,信息是从注册表中检索的。现在,我第二次用这个函数做同样的事情

struct GPUInfo {
    DWORD adaptersCount;
};

struct GPUInfo gpuinfo() {
    HKEY hKey;
    struct GPUInfo gpu = { 0 };

    LONG lRes = RegOpenKeyExW(
        HKEY_LOCAL_MACHINE,
        L"HARDWARE\DEVICEMAP\VIDEO",
        0,
        KEY_READ,
        &hKey
    );
    if (lRes == ERROR_SUCCESS) {
        DWORD dwBufferSize = sizeof(DWORD);
        ULONG nError = RegQueryValueExW(
            hKey,
            L"MaxObjectNumber",
            0,
            NULL,
            (LPBYTE)(&gpu.adaptersCount),
            dwBufferSize
        );

        RegCloseKey(hKey);
    }

    return gpu;
}

当我调试程序时,就像我说的,第一个函数工作但第二个函数此时抛出异常:

ULONG nError = RegQueryValueExW( // !!!! Access violation reading location 0x0000000000000004
    hKey,
    L"MaxObjectNumber",
    0,
    NULL,
    (LPBYTE)(&gpu.adaptersCount),
    dwBufferSize
);

我检查过注册表,路径确实存在。真的不明白为什么第一个有效而第二个无效。我接连打电话给他们

注意你的编译器警告。您正在通过 lpcbData(缓冲区长度)by value 而不是 by address.

它应该是这样的:

DWORD dwBufferSize = sizeof(gpu.adaptersCount);  // (2)
ULONG nError = RegQueryValueExW(
        hKey,
        L"MaxObjectNumber",
        0,
        NULL,
        (LPBYTE)(&gpu.adaptersCount),
        &dwBufferSize                // (1)
    );

变化:

  1. dwBufferSize前面加上&符号,就像你的第一个例子
  2. 使用sizeof您的实际结构成员。这是等效的,但在面对未来的变化时更安全。

参考: - RegQueryValueExW