簡體   English   中英

有沒有辦法幫助我 Clang Static Analyzer 理解全局常量對象?

[英]Is there a way for me to help Clang Static Analyzer understand global constant objects?

背景:由於原因,我的代碼喜歡以(非常輕量級的)類對象的形式從其函數返回成功/錯誤代碼值。 這工作正常,但是我很難讓 Clang Static 分析器了解發生了什么; 它的混亂導致它在分析我的程序時發出虛假的“未初始化值”警告。

這里有一些最小的示例代碼來說明/重現(錯誤)行為:

// my_status_t_class.h

#ifndef MY_STATUS_T_CLASS_H
#define MY_STATUS_T_CLASS_H

class status_t
{
public:
   status_t(int errorNumber) : _errorNumber(errorNumber) {/* empty */}

   bool IsError() const {return (_errorNumber != 0);}

private:
   int _errorNumber;
};

// A list of some common error codes
const status_t STATUS_NO_ERROR(0);
const status_t STATUS_DATA_NOT_FOUND(-1);
// [...]

#endif

// my_test_program.cpp

#include <stdio.h>
#include <stdlib.h>

#include "my_status_t_class.h"

status_t GetValue(int & ret) 
{
   if (rand()%2)
   {
      ret = 5;
      return STATUS_NO_ERROR;
   }
   else return STATUS_DATA_NOT_FOUND;
}

int main(int argc, char ** argv)
{
   int ret;
   if (GetValue(ret).IsError()) ret = 5;
   printf("ret=%i\n", ret);
   return 0;
}

當我在上面的代碼上運行scan-build時,它給出了這個 output:

$ scan-build g++ -std=c++17 my_test_program.cpp
scan-build: Using '/Users/jaf/llvm-project/build/bin/clang-16' for static analysis
testhashtable.cpp:20:8: warning: 2nd function call argument is an uninitialized value [core.CallAndMessage]
   printf("ret=%i\n", ret);
   ^~~~~~~~~~~~~~~~~~~~~~~

生成 1 個警告。

.... 它會生成有關錯誤的報告,可以在此鏈接中查看。

正如您從報告中看到的那樣,ClangSA 似乎認為我的GetValue() function 有可能返回STATUS_DATA_NOT_FOUND ,但隨后IsError()方法在main()內部返回 false,當ret局部變量未定義時用來。

實際上,這是不可能的IsError()將返回 true,因此main()將執行ret = 5; 因此,當我將ret傳遞給printf()時,它始終具有明確定義的值。

我的問題是,這是 ClangSA 中的錯誤嗎? 或者,如果沒有,是否有推薦的方法讓我在此處讓 ClangSA 理解/遵循我的status_t class 的語義? (看起來應該可以,因為代碼都在my_status_t_class.h header 文件中定義,ClangSA 可以直接訪問該文件)。

我確實注意到,如果我用#define聲明替換my_status_t_class.h中的常量聲明,我會得到我想要的行為,例如,如果我這樣做:

// my_status_t_class.h

[...]

// A list of some common error codes
#define STATUS_NO_ERROR       status_t(0)
#define STATUS_DATA_NOT_FOUND status_t(-1)
// [...]

...然后 ClangSA 不會產生虛假警告...但這當然是一個非常丑陋的解決方案,如果有更好的選擇,我想避免使用它。

我認為問題在於分析器無法看到STATUS_DATA_NOT_FOUND object 始終是一個錯誤,因此不能確定ret將始終被初始化。

它看不到的原因是因為STATUS_DATA_NOT_FOUND object 不是常量表達式,所以分析器無法在編譯時知道它的值。

解決此問題的一種方法是使用constexpr構造函數使STATUS_DATA_NOT_FOUND object 成為常量表達式:


class status_t
{
public:
   constexpr status_t(int errorNumber) : _errorNumber(errorNumber) {/* empty */}


constexpr status_t STATUS_DATA_NOT_FOUND(-1);

通過該更改,分析器應該能夠看到STATUS_DATA_NOT_FOUND始終是一個錯誤,因此它將知道ret將始終被初始化。

或者,您可以使STATUS_DATA_NOT_FOUND object 成為全局變量而不是常量 object,並使用常量表達式對其進行初始化:


status_t STATUS_DATA_NOT_FOUND = status_t(-1);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM