C ++内存指针练习中的未知崩溃

时间:2009-01-16 13:58:40

标签: c++ pointers crash

我最近编写了一个程序来帮助我理解C ++中内存指针的基础知识,我选择了一个简单的素数查找器。

我终于开始工作了。 (我的调试!)

我让它跑去看它走了多远,它得到了#815389,我的详细告诉我是65076的素数,我得到了一个应用程序崩溃。我能想到的一件事是我的注意力溢出,所以我把它们变成了多头,它们卡在了同一个地方。

是否有人能够帮助解释导致此问题的限制?

comp:WinVista 64位家庭高级版,6GB内存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;
};

(没关系用户名,它只是我使用的别名,所以我可以跟踪谷歌的所有帖子)

6 个答案:

答案 0 :(得分:7)

堆栈溢出?我看到check是递归的。

答案 1 :(得分:4)

我猜测two.nxt没有初始化。在C中,原始数据类型没有被初始化,这意味着它们具有在它现在占用的任何内存中发生的任何值。这意味着很可能在main()中,two.nxt = true,这会导致check()在无效指针上运行。尝试将其明确设置为false,看看它是否适合您。

[edit]如果这是问题,那么当你在check()中分配新的num时,更重要的初始化。

答案 2 :(得分: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 << ", ";
        }
     }
};

当然,递归本质可能是罪魁祸首,初始化问题是隐藏的,因为您可能正在运行调试版本。将递归形式转换为迭代形式留作练习。

答案 3 :(得分:1)

我可以看到几个问题:

  • 你正在分配一堆nums,但你没有检查std :: bad_alloc异常。你可能只是内存不足......
  • 如果nxtnum是!= 0,你不会在任何地方检查,即使我认为这样做是安全的,因为你解除引用它的唯一地方是守卫。然而,这并不是一种很棒的做法。
  • 正如Sean Edwards所提到的,num类没有构造函数,因此新创建的num的成员充满了几乎随机的垃圾。并且随机垃圾可能包括将nxt设置为非零值。我将添加以下构造函数,为其提供一组安全默认值:

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

  • 你真的不需要布尔值,我只检查nxtnum是非零。

  • 正如Jeff Yates所说,你可能会遇到堆栈溢出,因为递归函数的嵌套太深了,但它看起来并不像那样

答案 4 :(得分:0)

顺便提一下,如果您使用的是Microsoft编译器,则在定位x64时,int和long的大小相同。你的main函数中也有一个无限循环,因为1总是&lt; = 1000001。

答案 5 :(得分: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;
};

对于那些感兴趣的人