在我的 C++ Windows 服务代码中出现 C26xxx 错误
Getting C26xxx errors in my C++ Windows service code
我的代码出现错误。代码可以编译,但我仍然想摆脱警告。我查看了 Whosebug 和 google 并单击了将我带到 microsoft.com 页面的警告,对每个警告进行了解释,但我没有看到如何摆脱它们的具体示例。
这是 C++ 代码和警告。
void WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv);
VOID main() noexcept
{
CONST SERVICE_TABLE_ENTRY ste[] = { {L"MyService", ServiceMain}, {NULL, NULL} };
//C26485 Expression 'ste': No array to pointer decay (bounds.3).
StartServiceCtrlDispatcherW(ste);
}
// C26429 Symbol 'lpszArgv' is never tested for nullness, it can be marked as not_null (f.23).
// C26461 The pointer argument 'lpszArgv' for function 'ServiceMain' can be marked as a pointer to const (con.3).
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
{
// C26481 Don't use pointer arithmetic. Use span instead (bounds.1).
ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0);
...
}
感谢任何帮助。
这些不是编译器警告,而是代码分析警告(基于 CppCoreGuidelines), which give hints on how to improve code to prevent common errors - like null pointer dereferences and out of bound reads/writes. Fixing them might require use of gsl library of tools : https://github.com/microsoft/GSL.
//C26485 Expression 'ste': No array to pointer decay (bounds.3).
StartServiceCtrlDispatcherW(ste);
这会通知您有关潜在危险的调用,此函数不获取有关数组大小的信息,因此它可能会导致读取外部缓冲区。分析器不知道此函数依赖于最后一个元素被初始化为 null。您可以通过在堆上为 ste
分配内存并在 StartServiceCtrlDispatcherW
调用后释放来消除此警告,或者更好的方法是将分配的内存包装在 std::unique_ptr
中,甚至将条目存储在 std::vector
中
https://docs.microsoft.com/en-us/cpp/code-quality/c26485?view=msvc-170
// C26429 Symbol 'lpszArgv' is never tested for nullness, it can be marked as not_null (f.23).
// C26461 The pointer argument 'lpszArgv' for function 'ServiceMain' can be marked as a pointer to const (con.3).
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
您应该可以使用 gsl 修复此警告:
const auto args = gsl::span<LPWSTR>(lpszArgv, dwArgc);
然后像使用 lpszArgv 一样使用 args。有关如何使用 gsl 的说明,请参见此处:https://github.com/Microsoft/GSL
根据文档,调用 ServiceMain 时应始终使用 lpszArgv 中的至少一个元素:
...The first parameter contains the number of arguments being passed to the service in the second parameter. There will always be at least one argument. The second parameter is a pointer to an array of string pointers. The first item in the array is always the service name.
https://docs.microsoft.com/en-us/windows/win32/services/writing-a-servicemain-function
因此可以通过以下方式抑制此警告:
#pragma warning(suppress: 26429 26461)
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
或更好:
[[gsl::suppress(f.23)]]
[[gsl::suppress(con.3)]]
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
两个警告的链接:
https://docs.microsoft.com/en-us/cpp/code-quality/c26429?view=msvc-170
https://docs.microsoft.com/en-us/cpp/code-quality/c26461?view=msvc-170
// C26481 Don't use pointer arithmetic. Use span instead (bounds.1).
ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0);
..
如果您使用如上所示的 gsl::span,这将得到解决
我的代码出现错误。代码可以编译,但我仍然想摆脱警告。我查看了 Whosebug 和 google 并单击了将我带到 microsoft.com 页面的警告,对每个警告进行了解释,但我没有看到如何摆脱它们的具体示例。
这是 C++ 代码和警告。
void WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv);
VOID main() noexcept
{
CONST SERVICE_TABLE_ENTRY ste[] = { {L"MyService", ServiceMain}, {NULL, NULL} };
//C26485 Expression 'ste': No array to pointer decay (bounds.3).
StartServiceCtrlDispatcherW(ste);
}
// C26429 Symbol 'lpszArgv' is never tested for nullness, it can be marked as not_null (f.23).
// C26461 The pointer argument 'lpszArgv' for function 'ServiceMain' can be marked as a pointer to const (con.3).
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
{
// C26481 Don't use pointer arithmetic. Use span instead (bounds.1).
ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0);
...
}
感谢任何帮助。
这些不是编译器警告,而是代码分析警告(基于 CppCoreGuidelines), which give hints on how to improve code to prevent common errors - like null pointer dereferences and out of bound reads/writes. Fixing them might require use of gsl library of tools : https://github.com/microsoft/GSL.
//C26485 Expression 'ste': No array to pointer decay (bounds.3). StartServiceCtrlDispatcherW(ste);
这会通知您有关潜在危险的调用,此函数不获取有关数组大小的信息,因此它可能会导致读取外部缓冲区。分析器不知道此函数依赖于最后一个元素被初始化为 null。您可以通过在堆上为 ste
分配内存并在 StartServiceCtrlDispatcherW
调用后释放来消除此警告,或者更好的方法是将分配的内存包装在 std::unique_ptr
中,甚至将条目存储在 std::vector
中
https://docs.microsoft.com/en-us/cpp/code-quality/c26485?view=msvc-170
// C26429 Symbol 'lpszArgv' is never tested for nullness, it can be marked as not_null (f.23). // C26461 The pointer argument 'lpszArgv' for function 'ServiceMain' can be marked as a pointer to const (con.3). VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
您应该可以使用 gsl 修复此警告:
const auto args = gsl::span<LPWSTR>(lpszArgv, dwArgc);
然后像使用 lpszArgv 一样使用 args。有关如何使用 gsl 的说明,请参见此处:https://github.com/Microsoft/GSL
根据文档,调用 ServiceMain 时应始终使用 lpszArgv 中的至少一个元素:
...The first parameter contains the number of arguments being passed to the service in the second parameter. There will always be at least one argument. The second parameter is a pointer to an array of string pointers. The first item in the array is always the service name.
https://docs.microsoft.com/en-us/windows/win32/services/writing-a-servicemain-function
因此可以通过以下方式抑制此警告:
#pragma warning(suppress: 26429 26461)
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
或更好:
[[gsl::suppress(f.23)]]
[[gsl::suppress(con.3)]]
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
两个警告的链接: https://docs.microsoft.com/en-us/cpp/code-quality/c26429?view=msvc-170 https://docs.microsoft.com/en-us/cpp/code-quality/c26461?view=msvc-170
// C26481 Don't use pointer arithmetic. Use span instead (bounds.1). ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0); ..
如果您使用如上所示的 gsl::span,这将得到解决