C++ 数字范围超过40时出现堆栈溢出错误
程序应该提示输入一个数字范围,然后为该范围内的数字输出杂耍程序序列,但每当我输入一个超过40的范围时,就会出现堆栈溢出错误,不知道为什么 juggler_seq.exe中0x77354A3E(ntdll.dll)处未处理的异常:0xC00000FD:堆栈溢出(参数:0x00000001、0x00092FF4) //juggler_seq.cpp:定义控制台应用程序的入口点。 //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::字符串到_字符串(
#包括“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 "";
}