C ++ gdb错误读取变量:无法访问地址处的内存

时间:2019-05-05 12:27:35

标签: c++ segmentation-fault biginteger

我正在尝试解决一个问题,它希望程序输出n ^ 84601的结果。 (n = 0,1,...,10) 因此,我尝试使用大整数来解决它,并且在小数时效果很好,但在大数时却出现段错误。

#include <stdlib.h>
#include <iostream>
using namespace std;

const int MX = 100000;
struct BigInt {
    int ar[MX];
    int len;
    BigInt(int n) {
        int i = 0;
        while (n != 0) {
            ar[i] = n % 10;
            n /= 10;
            i++;
        }
        len = i;
    }
    BigInt times(BigInt x) {
        BigInt tmp(0);
        for (int i = 0; i < len; i++) {
            for (int j = 0; j < x.len; j++) {
                int r = ar[i] * x.ar[j] + tmp.ar[i + j];
                tmp.ar[i + j] = r % 10;
                tmp.ar[i + j + 1] += r / 10;
            }
        }
        for (int i = min(len + x.len, MX - 1);; i--) {
            if (tmp.ar[i] != 0) {
                tmp.len = i + 1;
                break;
            }
        }
        return tmp;
    }
    void print() {
        for (int i = len - 1; i >= 0; i--) {
            cout << ar[i];
        }
        cout << endl;
    }
};
BigInt poww(BigInt a, int n) {
    if (n == 1) {
        return a;
    }
    BigInt x = poww(a, n / 2);
    BigInt y = x.times(x);
    if (n % 2 == 1) {
        y = y.times(a);
    }
    return y;
}
int main(void) {
    ios::sync_with_stdio(false);
    int n;
    while (cin >> n) {
        if (n == 0)
            cout << 0 << endl;
        else if (n == 1)
            cout << 1 << endl;
        else
            poww(BigInt(n), 86401).print();
    }
    return 0;
}

当我将MX更改为10000并将86401更改为864时,它可以正确计算2 ^ 864。但是它将以2 ^ 86401出现段错误。

1 个答案:

答案 0 :(得分:1)

您的堆栈溢出。

  • 您的BigInt对象很大:它包含100001 int个对象,通常为400,004个字节。
  • 您在堆栈上分配了其中的几个(有些是不必要的:您应该真正通过const引用传递参数)。
  • 您有递归。
  • 典型的堆栈大小限制为8MB。

将上面的语句组合在一起,可以看到一次最多可以有20个BigInt在堆栈上。您的递归深度至少为17,因此为每个递归调用在堆栈上创建多个BigInt肯定会失败。

有一些解决方案:

  • 使用更高效的编码-当前您正在使用int保留一位数字,unsigned char会更合适
  • 在堆而不是堆栈上为数字分配空间。如果这样做,请注意rule of five