未使用変数の警告エラーをブロックする方法

14414 ワード

0 x 00はじめに
いくつかのc++のプロジェクトでは、-Werror-Wunused-parameterのようなコンパイルオプションがよく使用され、エンジニアがプログラムのコンパイル段階で、ランダムなコード検査によってコードの堅牢性を強化するのを支援します.
warningをerrorのコンパイルオプションとするのは個人にとって無視されやすいが、工業生産出力の製品として特に重要であり、これはプログラムの書く規範の個人能力レベルの体現だけでなく、プログラミングの白初渉製品の品質のコントロールでもある.そのため、多くの大規模なオープンソースプロジェクトでは、このような慎重な操作が行われています.
0 x 01問題の説明
コードを書く過程で、いくつかの変数が宣言されますが、使用されません.論理コードには一時的なコメントが必要かもしれません.例えば、この2日間cve-2019-5544という穴のソースコードを見たとき、slpはurlの合法性を検出する関数SLPCheckServiceUrlSyntaxを定義していることが分かったが、入ってみると介在していることが分かった.
int SLPCheckServiceUrlSyntax(const char * srvurl, size_t srvurllen)
{
     
   (void)srvurl;
   (void)srvurllen;

   /*!@todo Do we actually need to do something here to ensure correct
    * service-url syntax, or should we expect that it will be used
    * by smart developers who know that ambiguities could be encountered
    * if they don't?

   if (srvurllen < 8)
      return 1;
   if (strncasecmp(srvurl, "service:",8))
      return 1;
   return 0;

    */
   return 0;
}

著者らは,この曖昧な関数を使うと問題になる開発者がいなければ,具体的な論理を実現しないほうがよいと述べた.【黒人?】これにより,srvurlsrvurllenの2つの孤立した変数が残った.関数が直接returnされると、エラーが表示されます.
もちろん,この関数は直接戻るのではなく,本稿で紹介する方法を賢く用いて沈黙して誤りを報告し,後で詳しく述べる.
0 x 02問題の再現
プログラムソース
ファイル名:test_unuse.cc
 #include 
 #include 
 
 using namespace std;
 
 void bar(int a)
 {
     
     cout <<"a: "<<a<<endl;
 }
 
 void foo(int param1, int param2, string a)
 {
     
     bar(param1);
 }
 
 int main()
 {
     
     int i = 39; 
     int j = 20; 
     foo(i,j,"aa");
     return 0;
 }

コンパイル
~  test_unuse g++ -O0 test_unuse.cc -Werror -Wunused-parameter -std=c++11
test_unuse.cc:28:26: error: unused parameter ‘param2’ [-Werror=unused-parameter]
 void foo(int param1, int param2, string a)
                          ^
test_unuse.cc:28:41: error: unused parameter ‘a’ [-Werror=unused-parameter]
 void foo(int param1, int param2, string a)
                                         ^
cc1plus: all warnings being treated as errors

fooのパラメータparam 2とaが使用されていないため、エラーが発生しました.
ある特殊な原因(例えば、やっと半日かけて変数に名前をつけたが、この変数が役に立たないことに気づき、削除するのが我慢できない)から、私たちは何らかの方法でこのエラーを遮断し、変数を保持する必要がある.
0 x 03未使用変数エラーを優雅にマスク
考え方:もし私たちが何もしない文を書いたら、コンパイラをだまして私がこの変数を使ったと言った.unused parameterの間違いは現れないのではないでしょうか.
簡単に言えば、if条件判断でよく使われる空の文のように、何もしないことを示しています.この変数を使用して空の操作を実行できますか?
強制型変換を使用して、変数をvoid型に変換することは、私たちの最善の選択です(CとC++汎用).
(void)param1;

またはマクロの使用
#define UNUSED(expr) do { (void)(expr); } while (0)
...

void foo(int param1, int param2)
{
     
    UNUSED(param2);
    bar(param1);
}

QtにはQ_UNUSEDというマクロがありますが、このテクニックを使用しています.
では、新しい問題が来ました.迎えに来てください.
上で紹介した方法は1つの変数を遮蔽することができて、もし100個の変数を遮蔽したいならば、100個の(void)を書かないことができますか?
0 x 04複数の未使用変数エラーを優雅にブロック
テンプレートの右値参照を使用して、異なるタイプの配列変数を初期化し、voidという変数を初期化します.
簡単に言えば、変数がどんなタイプであっても、私は黒を触って直接これらの変数で配列を初期化し、この配列変数を統一的に変換すればいい.実は、異なる変数を1つの配列に入れることができて、本当に私のC++に対する認知能力を覆しました.しかし、事実上、この配列変数は正常に使用できないだけです.
// The USE(x, ...) template is used to silence C++ compiler warnings
// issued for (yet) unused variables (typically parameters).
// The arguments are guaranteed to be evaluated from left to right.
struct Use {
     
  template <typename T>
  Use(T&&) {
     }  // NOLINT(runtime/explicit)
};
#define USE(...)                                                   \
  do {                                                             \
    ::v8::base::Use unused_tmp_array_for_use_macro[]{__VA_ARGS__}; \
    (void)unused_tmp_array_for_use_macro;                          \
  } while (false)

使用の検証
#include 
#include 

using namespace std;

template <typename T>
inline T const& Max(T const& a, T const& b)
{
     
	return a<b?b:a;
}

struct Use {
     
  template <typename T>
  Use(T&&) {
     }  // NOLINT(runtime/explicit)
};
#define USE(...)                                                   \
  do {                                                             \
    Use unused_tmp_array_for_use_macro[]{__VA_ARGS__}; \
    (void)unused_tmp_array_for_use_macro;                          \
  } while (false)

void bar(int a)
{
     
	cout <<"a: "<<a<<endl;
}
#define UNUSED(expr) do { (void)(expr); } while (0)

void foo(int param1, int param2, string a)
{
     
	USE(param2, a);
    bar(param1);
}


int main()
{
     
	int i = 39;
	int j = 20;
	foo(i,j,"aa");
	return 0;
}

コンパイル実行、エラーなし
➜  test_unuse g++ -O0 test_unuse.cc -Werror -Wunused-parameter -std=c++11

0x05 Tips
  • は、マクロにおいて可変パラメータを表す変数__VA_ARGS__である.
  • 右値参照は、copyではなくローカル関数createのオブジェクトmoveを出力し、効率を向上させるパフォーマンスを向上させる新しい構文です.
  • int a[]{0};は配列を初期化するために使用される.

  • 0 x 05参考文献
    https://stackoverflow.com/questions/1486904/how-do-i-best-silence-a-warning-about-unused-variables https://www.runoob.com/cplusplus/cpp-templates.html