0

从 main 开始,我试图在 mymath.cpp 中调用一个素数函数——它有一些我不理解的非常奇怪的行为。(注意,该算法还不能工作——但这​​对我来说并不奇怪。)

奇怪的是,如果我注释掉这一行:

cout << "n:" << lastPrime->pnum <<"\n";

... 在 mymath.cpp 中,我在 main 中的循环只运行了两次。如果我把它留在里面,我在 main 中的循环一直运行到 i = 50;

主程序

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include "stat.h"
#include "mymath.h";

using namespace std;

int main()
{
    for (int i = 3; i<= 50; i++)
    {
        if (isPrime(i))
        {
            cout << i << " is prime!\n";
        }
        else
        {
            cout << i << " is NOT prime\n";
        }
    }

    return 0;
}

MYMATH.CPP

#include "mymath.h"
#include <math.h>
#include <iostream>

using namespace std;

prime two;
prime * lastPrime = &two;
prime * firstPrime = &two;

bool isPrime(long long n)
{
  two.pnum=2;
  prime * currentPrime = &two;

  if ( n < 2)
      return false;

  long long squareRoot = sqrt(n);

  while(true)
  {
      if (n % currentPrime->pnum==0)
      {
          //n is divisible by a prime number, nothing left to do.
          return false;
      }
      else
      {
          //n is not divisible by a prime... check next one
          {
          if (currentPrime->pprime == 0 || currentPrime->pnum > squareRoot)
              {
                  //this is prime
                  prime addPrime;
                  addPrime.pnum=n;
                  addPrime.pprime=0;
                  lastPrime->pprime=&addPrime;
                  lastPrime=&addPrime;
                  cout << "n:" << lastPrime->pnum <<"\n";
                  return true;
              }
              else
              {
                  //may not be prime, check next
                  currentPrime = currentPrime->pprime;
              }
          }
      }
  }
  return true;
}
4

2 回答 2

3

该代码具有未定义的行为,因为名为 的局部变量addPrime在其生命周期之外被使用:

    lastPrime->pprime=&addPrime;
    lastPrime=&addPrime;
    cout << "n:" << lastPrime->pnum <<"\n";
    return true;
} // 'lastPrime' is now a dangling pointer because it holds the address
  // of 'addPrime' whose lifetime has ended.

要更正,您需要改为动态分配primeusing new但是,看起来(没有prime我不确定的定义)代码正在构建prime遇到的 s 列表。建议使用 astd::vector<prime>来构建列表并让它为您管理内存。

如果 astd::vector<prime>不是一个选项,无论出于何种原因,请确保的所有实例prime都是动态分配的,而不是动态分配的实例和非动态分配的实例(例如 global )的混合,因为它对于非动态分配的对象two是非法的。delete

于 2013-06-28T16:39:39.623 回答
2

添加或删除无害代码时出现的问题几乎总是由错误的指针造成的;有时它会覆盖一些重要的东西,有时它会覆盖一些无关紧要的东西。

在这种情况下,坏指针来自于获取addPrime并保存它的地址。在块的末尾addPrime消失,指向它的指针变得无效。

于 2013-06-28T16:42:26.400 回答