提问人:JeffR 提问时间:12/6/2021 最后编辑:JeffR 更新时间:12/7/2021 访问量:278
在我的 C++ Windows 服务代码中出现 C26xxx 错误
Getting C26xxx errors in my C++ Windows service code
问:
我的代码中出现错误。代码可以编译,但我仍然想删除警告。我查看了 stackoverflow 和 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),它提供了有关如何改进代码以防止常见错误(如空指针取消引用和越界读取/写入)的提示。修复它们可能需要使用 gsl 工具库:https://github.com/microsoft/GSL。
C26485 表达式“ste”:没有指向指针衰减的数组(bounds.3)。 StartServiceCtrlDispatcherW(ste);
这会通知您有关潜在危险的调用,此函数不会获取有关数组大小的信息,因此可能会导致读取缓冲区外部。分析器不知道此函数依赖于要初始化为 null 的最后一个元素。您可以通过为堆上分配内存并在调用后释放来静音此警告,或者通过将分配的内存包装在内部甚至将条目存储在ste
StartServiceCtrlDispatcherW
std::unique_ptr
std::vector
https://learn.microsoft.com/en-us/cpp/code-quality/c26485?view=msvc-170
C26429 符号“lpszArgv”从不测试是否为空,可以将其标记为not_null (f.23)。 C26461 函数“ServiceMain”的指针参数“lpszArgv”可以标记为指向 const (con.3) 的指针。 VOID WINAPI ServiceMain(DWORD dwArgc、LPWSTR* lpszArgv)
您应该能够使用 gsl 修复此警告:
const auto args = gsl::span<LPWSTR>(lpszArgv, dwArgc);
然后使用 args,就好像它是 lpszArgv 一样。有关如何使用 gsl 的说明,请参阅此处:https://github.com/Microsoft/GSL
根据文档,应始终使用 lpszArgv 中的至少一个元素调用 ServiceMain:
...第一个参数包含第二个参数中传递给服务的参数数。总会有一个参数。第二个参数是指向字符串指针数组的指针。数组中的第一项始终是服务名称。
https://learn.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://learn.microsoft.com/en-us/cpp/code-quality/c26429?view=msvc-170 https://learn.microsoft.com/en-us/cpp/code-quality/c26461?view=msvc-170
C26481 不要使用指针算术。请改用 span (bounds.1)。 ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0); ..
如果您使用 gsl::span,如上所示,这将得到解决
评论