簡體   English   中英

C ++內存指針練習中的未知崩潰

[英]Unknown crash in a C++ Memory Pointers Exercise

我最近寫了一個程序來幫助我理解C ++中的內存指針的基礎,我選擇了一個簡單的質數查找器。

我終於得到它的工作。 (是的,用於調試!)

我讓它運行以查看進展情況,它達到素數#815389,我的冗長告訴我是65076素數,我遇到了應用程序崩潰。 我能想到的一件事是我的整數溢出,所以我將它們更改為多頭,它卡在同一位置。

有人能夠幫助解釋造成這種情況的限制嗎?

comp:WinVista 64位家庭高級版,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跟蹤我的所有帖子)

堆棧溢出? 我看到check是遞歸的。

我猜出two.nxt沒有初始化的事實。 在C語言中,原始數據類型不會被初始化,這意味着它們具有現在正在占用的任何內存中發生的任何事情的值。 這意味着在main()中更可能是two.nxt = true,這將導致check()在無效指針上運行。 嘗試將其顯式設置為false,看看是否適合您。

[edit]如果這是問題所在,則更重要的初始化是在check()中分配新的num時。

肖恩是正確的,two.nxt從未初始化。 實際上,從未為num的任何實例初始化num.nxt。 如果使類更健壯,則成員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 << ", ";
        }
     }
};

當然,遞歸性質可能是主要的罪魁禍首,因為您可能正在運行調試版本,所以隱藏了初始化問題。 練習是將遞歸形式轉換為迭代形式。

我可以看到幾個問題:

  • 您正在分配一堆數字,但沒有檢查std :: bad_alloc異常。 您可能只是內存不足而已...
  • 即使我認為這樣做是安全的,因為您取消引用nxtnum的唯一位置在保護,但您不會在任何地方檢查nxtnum是否為!= 0。 然而,這並不是一個很好的實踐。
  • 正如肖恩·愛德華茲(Sean Edwards)所提到的那樣,num類沒有構造函數,因此新創建的num的成員中充滿了幾乎是隨機的垃圾。 而且該隨機垃圾可能包括將nxt設置為非零值。 我將添加以下構造函數以為其提供一組安全的默認值:

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

  • 您實際上並不需要布爾值,我只是檢查nxtnum是否為非零。

  • 正如Jeff Yates所說的那樣,由於遞歸函數嵌套太深,您可能會遭受堆棧溢出的困擾,但是看起來遞歸函數似乎並沒有那么深。

順便說一句,如果您使用的是Microsoft編譯器,則在定位x64時int和long的大小相同。 您的主要功能中也有一個無限循環,因為1總是<= 1000001。

我已經開始運作了,謝謝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;
};

對於那些有興趣的人

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM