1

私は C++ 用の粒子重力相互作用シミュレーション プログラムに取り組んでおり、ほとんど機能するところまで来ていますが、説明のつかないばかげたエラーが発生して頭がおかしくなりました。

このプログラムには 2048 個の粒子があり、それらを 200 タイム ステップでシミュレートします。各状態で、他のすべての粒子からの正味の力に基づいて、各粒子の新しい位置、速度、および加速度を更新します。基本的に、これは quad_tree を反復処理してすべてのパーティクル値を更新する、私が書いた再帰関数です。

    void iterateThroughQuadTree(double alpha, double delta_t)
    {
        std::cout << particles_count << std::endl;
        if (particles_count > 10)
        {
            //std::cout << particles_count << std::endl;
            children[0]->iterateThroughQuadTree(alpha,delta_t);
            children[1]->iterateThroughQuadTree(alpha,delta_t);
            children[2]->iterateThroughQuadTree(alpha,delta_t);
            children[3]->iterateThroughQuadTree(alpha,delta_t);
        }
        if (particles_count > 0)
        {

          std::cout << *(particles_x) << " " << *(particles_y) << " " << *(particles_vx) << " " << *(particles_vy) << std::endl;
          double acc_magnitude = 0, distance = 0, unit_vector_x = 0, unit_vector_y = 0, x_displacement = 0, y_displacement = 0, theta = 0, x_acc = 0, y_acc = 0;
          for (size_t i = 0; i < particles_count; i++) {
              double temp_x_acc = 0;
              double temp_y_acc = 0;
              for (size_t k = 0; k < particles_count; k++) {
                  if (i != k) {
                      x_displacement = particles_x[k] - particles_x[i];
                      y_displacement = particles_y[k] - particles_y[i];
                      distance = sqrt(pow(x_displacement,2) + pow(y_displacement,2));
                      unit_vector_x = x_displacement / distance;
                      unit_vector_y = y_displacement / distance;
                      acc_magnitude = particles_m[k] / pow(distance,2);
//                    //theta = atan(y_displacement/x_displacement);
                      x_acc = acc_magnitude * unit_vector_x;
                      y_acc = acc_magnitude * unit_vector_y;
//                    //x_acc = (x_displacement);
//                    //y_acc = (y_displacement);
                      temp_x_acc = temp_x_acc + x_acc;
                    //temp_y_acc = temp_y_acc + y_acc;
                  }
              }
              //std::cout << temp_x_acc << " " << temp_y_acc << std::endl;
              particles_x[i] += ((particles_vx[i]*delta_t) + alpha*temp_x_acc*pow(delta_t,2));
              particles_y[i] += ((particles_vy[i]*delta_t) + alpha*temp_y_acc*pow(delta_t,2));
              particles_vx[i] += 2*alpha*temp_x_acc*delta_t;
              particles_vy[i] += + 2*alpha*temp_y_acc*delta_t;
//            if (i < 1) {
//                //std::cout << *(particles_x + i) << " ";
//            }
          }
        }
    }

関数の途中にある次の 2 行に注意してください。

temp_x_acc = temp_x_acc + x_acc;
//temp_y_acc = temp_y_acc + y_acc;

エラーは、これらの行の 1 つがコメント アウトされている場合 (どの行でも問題ありません)、プログラムが正常に動作することです。しかし、それらが両方ともコメント解除されている場合、数回繰り返した後にプログラムがクラッシュし、セグメンテーション違反が発生します。ValGrind Memcheck を使用しましたが、スタック オーバーフローがあると表示されます。両方の行を一緒にプログラムに入れることができない理由がわかりません。1 つは単純にすべての x 成分の加速度を合計し、もう 1 つは y 成分の加速度を合計します。+= 演算子が 2 つある場合、何らかのメモリの問題がありますか? 毎回変数を再初期化しようとしましたが、それでも同じ結果が得られます。なぜこれが起こっているのかについて何か考えがある場合は、私に説明していただけますか? ありがとうございます。

必要に応じて、プログラムの追加コードを投稿します。問題は、プログラムが大きいため、必要以上に投稿したくないことです。

4

1 に答える 1

0

あなたのコードをすべて見たわけではありませんが、私には説得力のある理論があります。あなたが示していないコードのどこかで、グローバル変数であるparticle_countの値を変更しているに違いありません。再帰関数は、particle_count が 10 を下回らない限り終了できない可能性があります。

temp_x_acc と temp_y_acc の両方が設定されている場合、particles_count の値が何らかの形で上昇し、ループの繰り返しがさらに多くなり、スタック オーバーフローが発生する可能性はありますか? 検証に役立つ健全性チェックとして、次のように静的カウンターを関数の先頭に追加することをお勧めします。

static int iteration=0;
iteration++;
cerr<<"Iteration: "<<iteration<<", "<<Particles count: "<<particles_count<<endl;

クラッシュする前にすべての出力を取得できるように、cerr の使用に注意してください。cout は、クラッシュしたときにストーリー全体を出力していない可能性があります。

通常、再帰コードでは、particle_count などの重要な変数を関数パラメーターとして渡す必要があります。私は、particle_count の値が予期しない方法で変化している可能性があると思います。

于 2013-11-15T01:33:34.590 に答える