0

私は最近、C++ でのメモリ ポインターの基本を理解するのに役立つプログラムを作成しました。単純な素数ファインダーを選びました。

私はついにそれを働かせました。(デバッグにどうぞ!)

そして、それがどこまで進むかを確認するために実行させました.65076番目の素数であることが詳細に表示され、#815389の素数に達し、アプリがクラッシュしました. 私が考えることができたのは、intがオーバーフローしていたので、それらをlongに変更したことです。同じ場所でスタックします。

誰かがこれを引き起こしている制限を説明するのを助けることができますか?

comp: WinVista 64 ビット Home Premium、6GB RAM AMD 4800+ X2 プログラムが 4,664K のメモリ使用量でクラッシュする

ソース:

#include <cstdlib>

#include <iostream>

\\\\(Backslashes added for readability)

using namespace std;

long number;
long numnum;

class num;

class num {

  public:

         long i;
         void check();
         bool nxt;
         num* nxtnum;
};

void num::check() {

 if (number % i != 0) {
            if (nxt == true) {
                    (*nxtnum).check();
            } else {
                   nxtnum = new num();
                   (*nxtnum).i = number;
                   numnum++;
                   cout << numnum << ":" << number << ", ";
                   nxt = true;
            };
 };
};


int main(long argc, char *argv[]){

  numnum = 1;
  cout << numnum << ":" << 2 << ", ";
  num two;
  two.i = 2;
  for (number = 3; 1<=1000001; number++) {
    two.check();
  };
  cout << endl;
  system("PAUSE");
  return EXIT_SUCCESS;
};

(ユーザー名は気にしないでください。これは私が使用する単なるエイリアスであるため、Google ですべての投稿を追跡できます)

4

6 に答える 6

7

スタックオーバーフロー?check再帰的であることがわかります。

于 2009-01-16T14:06:12.493 に答える
4

two.nxt が初期化されていないという事実を推測します。C では、プリミティブ データ型は初期化されません。つまり、現在占有しているメモリにたまたまあったものの値を持っています。つまり、main() では、two.nxt = true である可能性が高く、check() が無効なポインターで実行される可能性があります。明示的に false に設定してみて、それが機能するかどうかを確認してください。

[編集] これが問題である場合、より重要な初期化は、check() で新しい num を割り当てるときです。

于 2009-01-16T14:06:14.443 に答える
2

Sean の言うとおりです。two.nxt は初期化されません。実際、num.nxt は num のインスタンスに対して初期化されることはありません。クラスをより堅牢にする場合、メンバ nxt は不要です。代わりに nxt ポインターを使用できます。

class num
{
private:
    long i;
    num *nxtnum;
public:
    num (long value) : i (value), nxtnum (0) { }
    void check ()
    {
      if (number % i != 0)
      {
        if (nxtnum)
        {
          nxtnum->check ();
        }
        else
        {
          nxtnum = new num (number);
          cout << ++numnum << ":" << number << ", ";
        }
     }
};

もちろん、再帰的な性質がおそらく主な原因であり、おそらくデバッグビルドを実行していたため、初期化の問題は隠されていました。再帰形式から反復形式への変換は、演習として残されています。

于 2009-01-16T14:22:33.193 に答える
1

私が見ることができるいくつかの問題:

  • 多数の数値を割り当てていますが、 std::bad_alloc 例外をチェックしていません。単にメモリが不足している可能性があります...
  • nxtnum が != 0 の場合はどこもチェックしていませんが、逆参照する場所だけがガードしているので、チェックしても安全だと思います。それにもかかわらず、それはそれほど素晴らしい練習ではありません。
  • Sean Edwards が言及しているように、num クラスにはコンストラクターがないため、新しく作成された num のメンバーはかなりランダムなジャンクで満たされます。そして、そのランダムなジャンクには、ゼロ以外の値に設定されている nxt が含まれる場合があります。次のコンストラクターを追加して、安全なデフォルトのセットを提供します。

    num::num() : i(0)、nxt(false)、nxtnum(0) {}

  • ブール値は実際には必要ありません。nxtnum がゼロでないことを確認するだけです。

  • Jeff Yates が言うように、再帰関数の入れ子が深すぎるため、スタック オーバーフローが発生する可能性がありますが、それほど深く再帰するようには見えません。
于 2009-01-16T14:20:54.163 に答える
0

うまくいきました、Skizz に感謝します

#include <cstdlib>
#include <iostream>
#include <windows.h>

using namespace std;

long number;
long numnum;
class num;
num *two;
num *nn;
num *bre;

class num
{
    private:
        long i;
        num *nxtnum;
    public:
        num (long value) : i (value), nxtnum (0) { }
        void *check ()
        {
          if (number % i != 0)
          {
            if (nxtnum)
            {
              //nxtnum->check ();
              nn = nxtnum;
            }
            else
            {
              nxtnum = new num(number);
              cout << ++numnum << ":" << number << ", ";
              nn = bre;
            }
         }else{nn=bre;}
        }
};

int main(long argc, char *argv[])
{
    numnum = 1;
    cout << numnum << ":" << 2 << ", ";
    two = new num(2);
    nn=two;
    for (number = 3; 1<=1000001; number++) {
        while (nn!=bre){
                nn->check();
                Sleep(0);
                }
        nn=two;
    };
    cout << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
};

興味のある方へ

于 2009-01-16T16:34:34.657 に答える
0

ちなみに、Microsoft コンパイラを使用している場合、x64 をターゲットにすると int と long は同じサイズになります。1 は常に <= 1000001 になるため、メイン関数にも無限ループがあります。

于 2009-01-16T15:23:26.767 に答える