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)
);
变化:
- 在
dwBufferSize
前面加上&符号,就像你的第一个例子
- 使用
sizeof
您的实际结构成员。这是等效的,但在面对未来的变化时更安全。
参考:
- RegQueryValueExW
我有两个用 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)
);
变化:
- 在
dwBufferSize
前面加上&符号,就像你的第一个例子 - 使用
sizeof
您的实际结构成员。这是等效的,但在面对未来的变化时更安全。
参考:
- RegQueryValueExW