8

次のコードは、GCC(4.2-4.6)とClang(2.1)の両方で正常にコンパイルされますが、実行可能ファイルを実行すると、「バスエラー:10」が表示されます。理由がわかりません。

#include <iostream>

struct A
{
  static int const v;
  A() { ++*const_cast<int *>(&A::v); }
};

int const A::v = 0;

int main(int argc, char * argv[])
{
  A a, b, c;
  std::cout << a.v << std::endl;

  return 0;
}
4

7 に答える 7

12

関連する引用は次のとおりだと思います。

§ N3242 からの 7.1.6.1 (4):

ミュータブルと宣言されたクラス メンバーを変更できることを除いて、const オブジェクトをその有効期間中に変更しようとすると、未定義の動作が発生します。

例は、 を使用してポイントを示していconst_castます。James が指摘したように、引用は C++03 標準の §7.1.5 にあります。

少し詳しく説明します。その言語規則により、何かが宣言されているときに、コンパイラは読み取り専用メモリを使用できます (ターゲット アーキテクチャで利用可能な場合) const。このルールがなければconst、結果を恐れることなく常に -ness を捨てることができ、それを使用することは開発者の規律の問題にすぎません。このようにすれば、少なくとも UB を呼び出していることを人々に伝えることができます。これは通常、適切な抑止力になります。オブジェクトconst_castを操作できるようにするためにコンパイラをどのようにだますかは問題ではないため、それ自体はあまり関係がありません。const

于 2011-08-08T19:49:51.517 に答える
7

5.2.11.7:

オブジェクトの型によっては、const-qualifier をキャストする const_cast から生じるポインター、左辺値、またはデータ メンバーへのポインターを介した書き込み操作によって、未定義の動作が発生する場合があります (7.1.5.1)。

あなたの場合、読み取り専用セグメントにあるデータを変更しようとしています。

于 2011-08-08T19:40:53.420 に答える
4

const として宣言された変数を変更することは許可されていないためです。

于 2011-08-08T19:34:55.783 に答える
2

私は実際の問題に対する解決策を持っていません。const_cast非 const メンバー関数から const メンバー関数を呼び出し、const の結果を "const_cast" (非 const メンバー関数の変更可能な結果にする) ことを意図していない限り、使用しないでください。

しかし、私はあなたのデザインを改善するための提案があります:

class A
{
private:
  static int v;
public:
  A() { ++v; }
  static int get_v() { return v; }
};

int A::v = 0;

int main(int argc, char * argv[])
{
  A a, b, c;
  std::cout << a.get_v() << std::endl;

  return 0;
}
于 2011-08-08T19:36:18.413 に答える
2

const をキャストしたからといって、そのメモリへの書き込みに成功するとは限りません。

コンパイラの観点から、変数の定数性const_cast<T>を取り除くだけです。これにより、コンパイラは先に進み、コードを発行して変数に書き込むことができます。しかし、実行時に、コンパイラ/リンカがたまたま変数を読み取り専用メモリに配置した場合、どのようにキャストしても、ハードウェアはそこへの書き込みを停止します。

于 2011-08-08T19:37:37.800 に答える
2

基本的に、変数が宣言されている場合const、コンパイラは結果を読み取り専用メモリに出力できます。constオブジェクトへのポインター/参照を取得し、それを使用const_castして削除するとconst、未定義の動作が発生する可能性があります。

const_cast一般に、参照されているオブジェクトが non- である場合にのみ安全に使用できますconst(ポインター/参照が であってもconst)。

于 2011-08-08T19:50:54.490 に答える
1

問題はこの行です:

static int const v;

const を宣言したため、const_cast は未定義の動作を引き起こしています。この場合、バス エラーが発生して幸運です (私のシステムではセグメンテーション違反です)。

非 const を宣言すると、問題なく const_cast を呼び出すことができます。

于 2011-08-08T19:37:22.553 に答える