【问题标题】:I am getting "Segmentation Fault" without using pointers. What is happening?我在不使用指针的情况下得到“分段错误”。怎么了?
【发布时间】:2014-07-14 01:05:04
【问题描述】:

已解决:段错误是由无限(嗯,实际上无限)递归引起的。当我忘记考虑案例b = 0 时,无限递归发生在我的uint pow(uint a, uint b) 函数及其辅助函数中。当b = 0 时,b 将减少,将其环绕到unsigned int 限制,然后继续添加堆栈直到b 回到 1。

感谢@chris 帮助调试,感谢@vsoftco 建议无限递归。


我对 C++ 还是很陌生。我正在编写一个程序,它有 4 个函数,其中 3 个是递归的(我怀疑递归函数与这个问题有关)。

基本上,我知道当我进入以下代码行时遇到了段错误:

    uint right = (n % pow(10, i)) / pow(10, i - 1);

此代码在我的 bool isPalindrome(uint) 函数的 for 循环中。这是我掌握的与段错误有关的唯一信息。

我尝试在 stackoverflow 和 google 上查找段错误示例,但我找不到任何 与指针和类似内容有关的示例。

这里出了什么问题?任何和所有的帮助将不胜感激。另外,请解释您提出的任何建议,因为我对 C++ 还很陌生,并且打算尽可能多地学习。完整的源代码如下,我认为它对于这个问题是无价的。

/*
 * AUTHORS:        Thomas D. Fischer (a.k.a. gragas)
 * CREATION DATE:  ----:--:--        (YY:MM:DD)
 */

#include <iostream>
#include <time.h>

using namespace std;

typedef unsigned int uint;

bool isPalindrome(uint);
uint length(uint, uint count = 0);
uint pow(uint, uint);
uint powhelper(uint, uint, uint);

int main()
{
    clock_t start_time = clock();
    cout << "Running program..." << endl;

    cout << isPalindrome(12) << endl;

    cout << "Execution Time: " << double(clock() - start_time)/CLOCKS_PER_SEC;
}

bool isPalindrome(uint n)
{
    for(uint i = 1; i <= length(n)/2; i++)
    {
        uint left  = (n / pow(10, length(n) - i)) % 10;
        uint right = (n % pow(10, i)) / pow(10, i - 1);
        if( left != right )
            return false;
    }
    return true;
}

uint length(uint n, uint count)
{
    if(n != 0)
        return length(n /= 10, ++count);
    else
        return count;
}

uint pow(uint a, uint b)
{
    if(b != 1)
        return powhelper(a*a, --b, a);
    else
        return a;
}

uint powhelper(uint a, uint b, uint multiplier)
{
    if(b != 1)
        return powhelper(a*multiplier, --b, multiplier);
    else
        return a;
}

【问题讨论】:

  • 哪一行给出了段错误?相关变量有什么值?使用调试器。
  • 你可能在某处有无限递归(因此堆栈实际上溢出了),使用调试器看看发生了什么。
  • @chris 我发现了给我段错误的特定行。帖子已更新。
  • @chris 和 @vsoftco ,我发现了问题。 @vsoftco 你是对的,我没有考虑到我的 uint pow(uint a, uint b) 函数将 0 作为第二个参数 b。这会导致无限递归,因为递归在 b 达到 1 时停止,但是 b 从 0 开始并且仅减少,它永远不会达到 1。感谢你们俩帮助我解决了这个问题。
  • 递归实际上并不是无限的,只是非常大。

标签: c++ recursion segmentation-fault


【解决方案1】:

您的 pow() 函数无法处理 b=0 的情况。这发生在循环的第一次迭代中(我通过插入几个调试打印输出发现)。

这种情况下--b会溢出,变成一个很大的数,导致递归溢出栈。

段错误来自程序的堆栈溢出。

【讨论】:

    【解决方案2】:

    您的pow 函数没有正确处理0 的指数,这是您在循环的第一次迭代期间在有问题的行上传递的。您是否考虑过使用std::pow

    为了进一步详细说明,您在调用powhelper 时将指数从零递减。这很好地定义为模算术,所以你会得到一个非常大的数字,几乎肯定会导致堆栈溢出。

    【讨论】:

    • std::pow 是一个浮点函数,可能会带来与将浮点数转换为整数相关的所有问题 - 这里可能不是一个好的解决方案
    • @Matt McNabb 您能否进一步详细说明double 无法准确表示所有 32 位整数(假设 unsigned 在这里是 32 位)?
    • 你能证明它可以吗?
    猜你喜欢
    • 2012-04-07
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多