1

次の条件を満たすコードが、同じ入力に対して実行ごとに異なる出力を生成する可能性はありますか?

  • コードはシングル スレッドですが、スレッド セーフなランタイム ライブラリにリンクしています。
  • rand() または time() またはそれらの仲間への明示的な呼び出しはありません。
  • いくつかのヒープ メモリ割り当てがあります。
  • 未定義の動作を引き起こす (バグのある) コードが含まれている可能性があります。
4

6 に答える 6

8

「未定義の動作」とは、何でも起こり得ることを意味します。これには、プログラムの実行ごとに異なることが発生する可能性も含まれます。

たとえば、初期化されていないメモリを使用する場合、そのメモリに正確に何が含まれているかは、プログラムの実行ごとに異なる場合があります。

簡単な例:

int main() {
  char s[1024];
  s[1023] = '\0';
  std::cout << s << std::endl;
}

これは通常、実行されるたびに異なる文字列を出力します。ヒープ割り当てを使用せず、未定義の動作でさえないと思うので、おそらくあなたの質問に対する意図した解決策ではありません。

別の例としてnew、プログラムの実行ごとに異なるアドレスを返すことができます (ここでも UB はありません)。

int main(void) {
   std::cout << new int << std::endl;
}

したがって、未定義の動作がなくても「ランダム性」の原因があります。したがって、未定義の動作でも、プログラムの実行ごとに異なることが発生する可能性があります。

于 2010-08-22T14:34:13.887 に答える
1

「未定義の動作で何かが起こる可能性がある」という回答がたくさん得られるので、このトピックについては言いません。自分で書いていないプログラムがあり、決定論的である必要があり、それをデバッグする必要がある、またはそのようなプログラムがあると仮定します。

  • 最新の OS にはアドレスのランダム化があるため、アドレスを整数として使用する未定義の動作は非決定論的である可能性があります

  • によって返されるメモリmalloc()がゼロになることは保証されていませんが、OS は通常、ページを再利用する前にページをゼロにすることでプロセスの機密性を確保します。したがってmalloc()、スタックを使用する場合は、ゼロ化されたページまたはプロセスが以前に埋めたページのいずれかを取得する必要があるため、非決定性が導入されないようにする必要があります。

今のところ思いつくのはこれくらいです。

于 2010-08-22T14:43:13.283 に答える
0

他の人がすでに言ったことに加えて:

プログラムがユーザーと対話する場合、おそらく別のランダム性のソースが導入されます。ユーザーは、さまざまな順序で、またはさまざまなタイミングでさまざまなアクションを引き起こす可能性があります。これらのアクションが何であるかに応じて、プログラム内で微妙な違いが発生する可能性があります (メモリが異なる順序で割り当てられるなど)。

それをさまざまな形式の未定義の動作 (初期化されていないメモリの使用が良い例です) と組み合わせると、プログラムが実行されるたびに異なるように見える症状や、一見予測できない方法で終わる可能性があります。

于 2010-08-22T18:26:34.483 に答える
0

未定義の動作が予期しない結果につながる理由について は、次の投稿をお読みください。


次のプログラムはあなたの要件を満たしています。

#include <time.h>
#include <iostream>
int main() 
{
    std::cout << time(NULL);
}
于 2010-08-22T14:49:50.903 に答える
0

もちろん。

randまたはを呼び出さなくても、多くのことが実行ごとに異なりますtime

例えば:

  • 実行可能コードは別のアドレスにロードされる可能性があります。
  • ヒープ割り当ては異なるアドレスを返す可能性があります。
  • 使用するライブラリが呼び出す可能性があるrandか、またはtime知らないうちに、
  • すべての OS が割り当て時にすべてのプロセス メモリをゼロにするわけではなく、メモリからガベージ値を読み取る可能性があります。
  • 新しく割り当てられたメモリ ページがゼロになったとしても (よくあることですが)、メモリ割り当てが常に新しいページを返すという保証はありません。それらは、以前に使用されたメモリのチャンクを返す場合がありますが、これはゼロにはなりません。また、メモリ アロケータはおそらく決定論的ではないため、これが発生する場合もあれば、発生しない場合もあります。

そしてもちろん、あなたの最後のポイントはそれに答えます。コードに未知のバグが含まれている場合、それについて何も推測することはできません。それらのバグの 1 つが、呼び出さrandないと思っていたのに呼び出してしまう場合はどうすればよいでしょうか?

UB について賢くなろうとしないのが最善です。未定義の場合は未定義であり、「この場合はそれほど悪くない」と推論しようとすると、自分で穴を掘っているだけです。そうかもしれないから。

于 2010-08-22T17:48:10.793 に答える
0

最後の条件がこの質問に対する答えのようです。これを除いて、たとえば、 time() 呼び出しとその結果を使用した計算について考えることができます。

于 2010-08-22T14:35:26.103 に答える