20

いくつかの C++ コードの大幅なリファクタリングを行ったところ、私が気付いていない暗黙的な変換に起因する多数のバグが発見されました。

struct A *a();

bool b() {
    return a();
}

void c() {
    int64_t const d(b());
}

問題

  1. ではb、 の戻り値の型aは暗黙のうちに にキャストされboolます。
  2. ではc、 から返された値bはサイレントに に昇格されint64_tます。

質問

プリミティブ型間の暗黙的な変換に関する警告またはエラーを受け取るにはどうすればよいですか?

ノート

  1. の使用は-Wconversion、上記の例とは関係のないいくつかの任意の変換のみをピックアップするようです。
  2. BOOST_STRONG_TYPEDEFはオプションではありません (ディスク構造で使用されるため、私のタイプは POD である必要があります)。
  3. C も重要ですが、この問題は C++ コード ベースに関連しています。
4

6 に答える 6

7

C++ プログラミング言語、第 3 版、付録 C.6、つまり「暗黙の型変換」では、Bjarne Stroustrup が変換をプロモーション変換として分類しています。 (ケース 1)。

変換について、彼は次のように述べています。そして「コンパイラは多くの疑わしい変換について警告することができます。幸いなことに、多くのコンパイラは実際にそうしています。」

反対側のプロモーションは安全であり、コンパイラはそれらに警告を発することになっていないようです.

通常、コンパイラの警告は必須ではありません。通常、C++ドラフトと最終的な ANSI ドキュメントでは、「実装者は警告を発行する必要がある」と報告されています。必要に応じて、詳細について自分で確認できます。

編集: C++11 の注記を追加:

C++ プログラミング言語第 4 版では、第 3 版の付録が報告され、セクション 10.5「暗黙の型変換」として再び拡張されました。

以前の考慮事項と同じであるため、C++11 は「縮小変換」をより正確に定義し、{}-initializer 表記法 (6.3.5) を追加します。この表記法では、切り捨てがコンパイル エラーにつながります。

于 2014-01-29T09:08:34.090 に答える
2

A*Microsoft Visual C ++は、からへの変換の絞り込みについて警告を出しboolます。

コンパイラ警告C4800を参照してください

一方、プロモーションは「危険な」変換ではありません。データを失うことは不可能だからです。

編集:デモンストレーション

C:\Users\Ben>copy con test.cpp
bool f( void ) { return new int(); }
^Z
        1 file(s) copied.

C:\Users\Ben>cl /c /W4 test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(1) : warning C4800: 'int *' : forcing value to bool 'true' or 'false' (
performance warning)
于 2010-12-18T22:43:54.110 に答える
2

gcc を使用している場合は、 -Wall -Wextra を試してみましたか?

GCC でない場合は、コンパイラの詳細を投稿してください。

于 2010-12-18T08:10:15.533 に答える
1

私が理解している限り、プリミティブ型間の暗黙的な変換を制御することはできません。これは標準で義務付けられており、準拠するコンパイラーはサイレントに実行します。

BOOST_STRONG_TYPEDEFのようなアプローチが問題で機能しないことを確認しますか?仮想メンバー関数がなく、プリミティブデータメンバーが1つしかないクラスは、基本的にPODデータ型にすぎません。同じアプローチに従うだけで、基本プリミティブ型への変換のみを許可できます。例:

#include <iostream>
#include <stdexcept>

struct controlled_int {
  // allow creation from int
  controlled_int(int x) : value_(x) { };
  controlled_int& operator=(int x) { value_ = x; return *this; };
  // disallow assignment from bool; you might want to use BOOST_STATIC_ASSERT instead
  controlled_int& operator=(bool b) { throw std::logic_error("Invalid assignment of bool to controlled_int"); return *this; };

  // creation from bool shouldn't happen silently
  explicit controlled_int(bool b) : value_(b) { };

  // conversion to int is allowed
  operator int() { return value_; };

  // conversion to bool errors out; you might want to use BOOST_STATIC_ASSERT instead

  operator bool() { throw std::logic_error("Invalid conversion of controlled_int to bool"); };

  private:
    int value_;
};

int main()
{
  controlled_int a(42);

  // This errors out:
  // bool b = a;

  // This gives an error as well:
  //a = true;

  std::cout << "Size of controlled_int: " << sizeof(a) << std::endl;
  std::cout << "Size of int: " << sizeof(int) << std::endl;

  return 0;
}
于 2010-12-18T08:50:21.553 に答える
1

利用可能な静的分析ツールのいずれか、clint や C++ に相当するプログラム、または市販のツールのいずれかを使用できます。これらのツールの多くは、問題のある暗黙的な変換を見つけ出すことができます。

于 2010-12-18T21:43:41.513 に答える
0

問題を診断するために、カスタムの clang プラグインを作成します。これは LibreOffice コードで多くのことを行います。インスピレーションが必要な場合は、http://cgit.freedesktop.org/libreoffice/core/tree/compilerplugins/clangでソースを参照してください。

于 2015-06-14T11:28:48.017 に答える