C++ 数字范围超过40时出现堆栈溢出错误

C++ 数字范围超过40时出现堆栈溢出错误,c++,runtime-error,overflow,C++,Runtime Error,Overflow,程序应该提示输入一个数字范围,然后为该范围内的数字输出杂耍程序序列,但每当我输入一个超过40的范围时,就会出现堆栈溢出错误,不知道为什么 juggler_seq.exe中0x77354A3E(ntdll.dll)处未处理的异常:0xC00000FD:堆栈溢出(参数:0x00000001、0x00092FF4) //juggler_seq.cpp:定义控制台应用程序的入口点。 // #包括“stdafx.h” //示例程序 #包括 #包括 #包括 #包括 #包括 模板 std::字符串到_字符串(

程序应该提示输入一个数字范围,然后为该范围内的数字输出杂耍程序序列,但每当我输入一个超过40的范围时,就会出现堆栈溢出错误,不知道为什么 juggler_seq.exe中0x77354A3E(ntdll.dll)处未处理的异常:0xC00000FD:堆栈溢出(参数:0x00000001、0x00092FF4)

//juggler_seq.cpp:定义控制台应用程序的入口点。 //

#包括“stdafx.h”
//示例程序
#包括
#包括
#包括
#包括
#包括
模板
std::字符串到_字符串(T值){
std::ostringstream os;
os s;
std::cout>e;
对于(长整数y=s;y!=e+1;y++){
推回(变戏法者(y));
}
std::string com=“”;
整数计数=0;
int ref=0;
for(it=ans.begin();it!=ans.end();it++){
std::cout我看到的问题:

  • 语法

    return jugglers(long int(pow(n, (1.0 / 2.0))), ans);
    
    应该是编译器错误。正确的方法是:

    return jugglers((long int)(pow(n, (1.0 / 2.0))), ans);
    
    或者,更好的是

    return jugglers(static_cast<long int>(pow(n, (1.0 / 2.0))), ans);
    
  • 整数溢出

    当调用
    pow
    返回的数字变大以适应
    long int
    时,下一次调用
    pow
    会导致错误。在我的测试环境中,数字163导致了该问题。在某个点上,
    n
    的值达到
    -9223372036854775808
    并停留在那里,导致堆栈溢出。这非常接近于
    LONG_MIN
    -9223372036854775807

  • 我不明白为什么
    n
    不会在奇数和偶数之间翻转flob。这也会导致堆栈溢出。在前面的例子中,
    n
    的值由于奇数序列而不断增加

  • 通过将参数类型更改为
    unsigned long
    并将第一个检查更改为:

    if (n <= 1){
    

    从输出中可以看出,终止非常突然,不符合逻辑。

    您的代码正常。问题来自长整数溢出

    我用一些额外的显示对它进行了测试:在n到36的情况下,递归函数会收敛。在37的情况下,您会溢出一个长int可以容纳的最大值。然后,您的递归性会被破坏,而不会收敛,这会触发堆栈溢出

    如果使用
    long-long
    它将起作用(直到下一次容量溢出):

    防止数字溢出导致堆栈溢出:

    如果您想使其更加健壮,可以尝试预测溢出:

    • juggler()
      的偶数分支上,您将使用较小的数字进行递归调用(因为将幂提高到1/2意味着平方根,这里n>1)。因此不会发生任何不好的事情
    • 在奇数分支上,您将使用大于n的数字进行递归调用。如果存在整数溢出,则提高ot的3/2幂很可能会计算出一个小于当前值的数字。很容易监视这种情况,并以错误消息停止:

          ... 
          long long int r = (long long int)(pow(n, (3.0 / 2.0)));
          if (r>n)
              return jugglers(r, ans);
          else {
              std::cout<< "Integer overflow at "<<n<<std::endl; 
              return ""; 
          }
          ...
      
      。。。
      长整型r=(长整型)(功率(n,(3.0/2.0));
      如果(r>n)
      返回杂耍者(r,ans);
      否则{
      
      std::coutus通常堆栈溢出是由于数组结束或执行太多递归调用造成的。您的第一步是使用内置调试器或gdb缓慢、痛苦地逐步遍历您自己的代码,并找出其发生的位置和原因。:-)祝您玩得开心!这就是编程的全部内容。哈,哈使用一个很酷的程序也会有帮助。但是找到那些bug也会很有趣。:-)使用你最喜欢的调试器来逐步检查代码,检查a)是否一切正常,b)递归深度是否变大,c)是否
      n
      变大。对于偶数和
      n^3/2
      用于奇数。是否有任何原因使它们在堆栈溢出之前不会在奇数和偶数之间切换?这可能会导致一些非常大的数字。例如,从37开始,达到的最大值是24906114455136。因此,系统上的
      long
      最小值需要为64位。即使如此,我也不会进行精简k使用
      pow
      是可行的,因为
      double
      只有大约16位精度。@user3386109有趣的评论。不过,您假设采用IEC559编码。您应该避免硬编码数字,而更喜欢
      (1
      
      if (n <= 1){
      
      163,2081,94931,29249071,158186025767,62914706160224992,250828041,3972502044577,7917648072381635584,2813831564,53045,12217059,42702176063,8824193242915619,1
      
      std::string jugglers(long long int n, std::string ans = ""){
          ...
              return jugglers((long long int)(pow(n, (1.0 / 2.0))), ans);
          ...
              return jugglers((long long int)(pow(n, (3.0 / 2.0))), ans);
      }
      
          ... 
          long long int r = (long long int)(pow(n, (3.0 / 2.0)));
          if (r>n)
              return jugglers(r, ans);
          else {
              std::cout<< "Integer overflow at "<<n<<std::endl; 
              return ""; 
          }
          ...
      
             if (n>pow(std::numeric_limits<long long int>::max(), 2.0/3.0)) {
                  std::cout<<std::endl<<"Fatal error for "<<n<<std::endl; 
                  return "";
              }