Переменная при чтении ошибки gdb в C ++: невозможно получить доступ к памяти по адресу - PullRequest
1 голос
/ 05 мая 2019

Я пытаюсь решить проблему: программа хочет вывести результат 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 Ответ

1 голос
/ 05 мая 2019

У вас переполнение стека.

  • Ваш BigInt объект довольно большой: он содержит 100001 int s, что обычно составляет 400 004 байта.
  • Вы выделяете несколькоиз них в стеке (некоторые из них не нужны: вы должны действительно передавать аргументы по константной ссылке).
  • У вас есть рекурсия.
  • Типичный предел размера стека составляет 8 МБ.

Объедините вышеприведенные операторы вместе, и вы увидите, что в стеке одновременно может быть не более 20 BigInt с.Ваша глубина рекурсии не менее 17, поэтому создание более одного BigInt в стеке для каждого рекурсивного вызова гарантированно завершится неудачей.

Существует несколько решений:

  • useболее эффективное кодирование - в настоящее время вы используете int для хранения одной цифры, unsigned char будет более уместным
  • выделяет место для цифр в куче, а не в стеке.Если вы это сделаете, помните о правиле пяти .
...