【问题标题】:Unknown crash in a C++ Memory Pointers ExerciseC++ 内存指针练习中的未知崩溃
【发布时间】:2009-01-16 13:58:40
【问题描述】:

我最近写了一个程序来帮助我理解 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;
};

(别介意用户名,这只是我使用的别名,因此我可以使用 google 跟踪我的所有帖子)

【问题讨论】:

  • 嘿!看起来你正在使用 Dev-C++ ...猜猜我怎么知道?

标签: c++ pointers crash


【解决方案1】:

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

【讨论】:

  • 我以为这个问题是个笑话 :)
  • 我也是,但以防万一,我正在回答它。 :)
  • 递归总是可以转化为迭代的。
【解决方案2】:

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

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

【讨论】:

  • 好吧,在这种情况下,我会更多地关注 Jeff Yates 的回答。 :)
  • +1 肖恩发现了这一点。即使这不能解决崩溃,Sean 也是绝对正确的,您使用的是 two.nxt 而不初始化它,因此它的行为可能因编译而异,甚至运行时运行。
  • 顺便说一下,作为单独的 nxt 数据成员的替代方案,C/C++ 程序员通常只需在列表末尾将 nxtnum 设置为 NULL 并对其进行测试。
【解决方案3】:

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 << ", ";
        }
     }
};

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

【讨论】:

  • 谢谢,我从你的编码中提取了一些东西,并会努力让它正常工作。
【解决方案4】:

我可以看到几个问题:

  • 您分配了一堆数字,但您没有检查 std::bad_alloc 异常。您可能只是内存不足...
  • 如果 nxtnum 为 != 0,则您不会检查任何地方,尽管我认为这样做是安全的,因为您取消引用它的唯一地方是保护它。不过,这并不是一个很好的练习。
  • 正如 Sean Edwards 所提到的,num 类没有构造函数,因此新创建的 num 的成员充满了几乎随机的垃圾。并且该随机垃圾可能包括将 nxt 设置为非零值。我会添加以下构造函数来为其提供一组安全的默认值:

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

  • 您并不需要布尔值,我只需检查 nxtnum 是否非零。

  • 正如 Jeff Yates 所说,由于递归函数嵌套太深,您可能会遇到堆栈溢出,但它看起来不会递归 那么 深。

【讨论】:

  • 它必须递归多深?
【解决方案5】:

顺便说一下,如果您使用的是 Microsoft 编译器,则在面向 x64 时,int 和 long 的大小相同。您的主函数中还有一个无限循环,因为 1 始终是

【讨论】:

  • 是的,我想看看它会走多高
  • 您始终可以将中间条件留空,或将“true”放在那里。
【解决方案6】:

我已经成功了,谢谢 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;
};

对于那些有兴趣的人

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多