【问题标题】:Getting C26xxx errors in my C++ Windows service code在我的 C++ Windows 服务代码中出现 C26xxx 错误
【发布时间】:2022-01-11 17:37:39
【问题描述】:

我的代码出现错误。代码编译,但我仍然想摆脱警告。我查看了 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);
...

}

感谢任何帮助。

【问题讨论】:

  • 这些是来自 MS 代码分析器的消息(注意它们在消息中没有说警告或错误)。它们不是错误,而是来自 MS 的规则驱动代码分析器的消息。我通常不会默认打开它(分析器),但偶尔会打开它并对每个报告做出判断。例如C26481 NO_POINTER_ARITHMETIC
  • 请针对每个代码分析警告提出一个问题。你会发现有些(甚至可能全部)以前被问过和回答过。

标签: c++ windows service warnings compiler-warnings


【解决方案1】:

这些不是编译器警告,而是代码分析警告(基于CppCoreGuidelines),它提供了有关如何改进代码以防止常见错误(如空指针取消引用和越界读/写)的提示。修复它们可能需要使用 gsl 工具库:https://github.com/microsoft/GSL

//C26485 表达式“ste”:没有指向指针衰减的数组(bounds.3)。 StartServiceCtrlDispatcherW(ste);

这会通知您潜在的危险调用,此函数不会获取有关数组大小的信息,因此它可能会导致读取外部缓冲区。分析器不知道这个函数依赖于最后一个元素被初始化为空。您可以通过在堆上为ste 分配内存并在StartServiceCtrlDispatcherW 调用之后释放来消除此警告,或者通过将分配的内存包装在std::unique_ptr 中甚至将条目存储在std::vector 中更好

https://docs.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);

然后像使用 lpszArgv 一样使用 args。有关如何使用 gsl 的说明,请参见此处:https://github.com/Microsoft/GSL

根据文档,调用 ServiceMain 时应始终使用 lpszArgv 中的至少一个元素:

...第一个参数包含在第二个参数中传递给服务的参数数量。总会有至少一个论点。第二个参数是一个指向字符串指针数组的指针。数组中的第一项始终是服务名称。

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 不要使用指针算法。改用 span (bounds.1)。 ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0); ..

如果你使用 gsl::span,这将得到解决,如上所示

【讨论】:

  • 太棒了,谢谢!有没有办法从 Visual Studio 中的 C++ 项目设置中将其关闭?
  • 它在项目/属性/代码分析器下。全部设置为否。
猜你喜欢
  • 1970-01-01
  • 2019-04-24
  • 1970-01-01
  • 2023-02-21
  • 1970-01-01
  • 2021-09-17
  • 2015-08-10
  • 1970-01-01
  • 2019-06-22
相关资源
最近更新 更多