0

ちょっと、これらの警告のいずれかが起動時に.exeをクラッシュさせるのではないかと思っていました. 警告は次のとおりです。

Warning 1   warning C4244: '=' : conversion from 'double' to 'int', possible loss of data   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\stats.cpp 54  1   MaroonedCA2
Warning 2   warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\player.cpp    75  1   MaroonedCA2
Warning 3   warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\player.cpp    92  1   MaroonedCA2
Warning 4   warning C4018: '<' : signed/unsigned mismatch   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\inventory.cpp 63  1   MaroonedCA2

1

int stats[SIZE];
    stats[0] = Status.health;
    stats[1] = Status.strength;
    stats[2] = Status.hitpoints;
    stats[3] = Status.armour;
    stats[4] = Status.luck;

運はダブルで、キャストされていません。

2

 int Player :: hitPoints()
    {
        srand(time(0)); // seed random number generator based on current time
        int randomNumber= rand(); // generate random number
        int hitPoints = (randomNumber% 15) + 1; // get a number between 1 and 20
        return hitPoints;
    }

3

int Player :: fatigue()
{
    srand(time(0)); // seed random number generator based on current time
    int randomNumber= rand(); // generate random number
    int fatigue = (randomNumber% 5) + 1; // get a number between 1 and 5
    return fatigue;
}

4

for (int i= 0; i< inventory.size(); ++i)
        cout<< inventory[i] << endl;
    }
    cout << "\n-----------------------------------------\n";
4

4 に答える 4

2

クラッシュを誘発する可能性が実際にあると私が見ることができる唯一のものは、最後のものです。の場合inventory.size() > INT_MAX、典型的な実装では、最終的に負のインデックスから読み取ることになります。

あなたのプログラムが実際に起動中にクラッシュしていると仮定すると、これが問題の原因であるとすれば、私はむしろ驚くでしょう。これは、考えられる問題の原因というよりも理論的な可能性です。まず、起動時に、inventory.size() がおそらく 0 であるため、オーバーフローは発生しないと思います。次に、起動時ではなく、コマンドに応答してインベントリを表示するだけだと思います。そのため、このコードは起動時に実行されない可能性があります。

他のものには問題がありますが、クラッシュにつながる可能性はまったくありません.

たとえば、例 2 と 3 はsrand間違って使用されています。これを含むほとんどの通常のプログラムは、プログラムの起動時に一度だけ呼び出す必要があり、二度と呼び出す必要はありませsrand。これにより、「乱数」が本来よりもはるかに予測可能になりますが、クラッシュすることはありません。

于 2012-12-09T13:25:21.287 に答える
1

単独では、これらの警告のいずれもがクラッシュを引き起こす可能性はありません。ただし、予期しない値にうまく応答しない他の関数が誤って呼び出される可能性があります。

クラッシュが発生した理由を確認するには、クラッシュのスタック トレースを取得する必要があります。デバッグは別のトピックであり、Google から多くの情報を得ることができます :)

于 2012-12-09T13:22:31.977 に答える
1

あなたのプログラムはクラッシュしますか?

通常、これらの警告は、たとえば double を int に変換するが、この int が 0 になるかどうかをチェックせずに 0 で除算するなど、プログラムの特別なケースを見逃さない限り、それほど多くの問題を引き起こすことはありません。

すべての警告を見てみましょう。

Warning 1   warning C4244: '=' : conversion from 'double' to 'int', possible loss of data

int が double のすべての値を格納できないことは明らかですが、問題を引き起こす可能性のある値 (0 による変換など) になる可能性があることを念頭に置いている限り、変換しても問題はありませんが、これはあなたのintで何をしますか。int toint = static_cast<int>(yourdouble);警告をスローしないようにしてください。

Warning 2   warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data

time_t は通常 8 バイトで、uint は 4 バイトしかないため、明らかにすべての情報を内部に保存することはできません。データが失われると、値を期待しているのに別の値を取得している場合に混乱が生じる可能性があります。

Warning 4   warning C4018: '<' : signed/unsigned mismatch

これでも問題ありません。一方が負の値で、もう一方が負の値である可能性があること、または一方の最大値が他方の最大値よりも高いことを通知するだけです。符号なしのみが必要な場合に整数を符号なしとして定義するプログラマの怠惰のために通常発生する非常に一般的な警告です。

編集:VCを使用していると思います。以下は、警告を無視する方法の例です。警告を取り除くことができず、完全に安全に無視できると確信している場合 (once パラメータを使用することを強くお勧めします):

http://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

于 2012-12-09T13:28:16.710 に答える
1

各警告は、何かが正しくないことを示しています。これは、他のコードに影響を与える可能性があります。


の …

int stats[SIZE];
stats[0] = Status.health;
stats[1] = Status.strength;
stats[2] = Status.hitpoints;
stats[3] = Status.armour;
stats[4] = Status.luck;

Status.luckof typeを使用doubleすると、情報が失われるか、一般的すぎるタイプを使用します。情報が失われると、後でクラッシュする可能性があります。一般的すぎるタイプは、他の場所でバグを引き起こす可能性があります。

修正は、これら 2 つの可能性のどちらであるかによって異なります。


int Player :: hitPoints()
{
    srand(time(0)); // seed random number generator based on current time
    int randomNumber= rand(); // generate random number
    int hitPoints = (randomNumber% 15) + 1; // get a number between 1 and 20
    return hitPoints;
}

time(0)の型から の引数の型への暗黙的な変換に依存していますsrand

timeゲームのエントロピーのソースとしてはおそらく問題ありません (ただし、繰り返し呼び出されるサイコロを振るプログラムでは問題ありません)。ただし、ここでは a を使用してstatic_castください。文書化された仮引数の型に。


int Player :: fatigue()
{
    srand(time(0)); // seed random number generator based on current time
    int randomNumber= rand(); // generate random number
    int fatigue = (randomNumber% 5) + 1; // get a number between 1 and 5
    return fatigue;
}

乱数ジェネレーターを再初期化しています。それはおそらくバグです。プレイヤーが疲労するたびに同じ動作を繰り返したいとは思いません。


for (int i= 0; i< inventory.size(); ++i)
    cout<< inventory[i] << endl;
    }
cout << "\n-----------------------------------------\n";

中かっこまたは中かっこが欠けている、および/またはインデントの問題があります。残念ながらコンパイルされました。しかし、それを修正します。

符号付き/符号なしの不一致iは、符号付きと符号なしの比較に関するsize_tものですinventory.size()。状況によっては、これにより厄介なバグが発生する可能性があります。たとえば、式

string( "hello" ).size() < -3

が符号なし型に暗黙的に昇格され、ラップアラウンドが行われるtrueため、常に になります。それは非常にばかげています。そして、非常に知っておく価値があります。-3

ループの最適な修正はsize、サイズ値を符号付きにキャストする関数を使用することです。

typedef ptrdiff_t Size;

template< class Item >
Size size( std::vector<Item> const& v ) { return v.size(); }

それから

for (int i= 0; i < size( inventory ); ++i)
{
    cout<< inventory[i] << endl;
}

これにより、ソリューションが一元化され、将来のすべてのコードで機能します。

ループ制御変数を符号なし型に変更すると、問題 (特に暗黙の変換の問題) が別の場所に押しやられます。一般に、このような暗黙の変換に関する警告は表示されないことに注意してください。ほとんどのコンパイラは、直接比較に対してのみ警告します。

さらに一般的なsize関数については、次のように定義できます。

template< class Container >
Size size( Container const& c ) { return end( c ) - begin( c ); }

ここでbegin、 およびはヘッダーendの C++11 関数です。<utility>

于 2012-12-09T13:38:54.797 に答える