Таким образом, моя программа выполняется так, как ожидалось, и выводит правильный результат. Единственная проблема заключается в том, что после ее завершения он не выходит. Если я подожду еще несколько секунд, появится окно с сообщением "bignumbs.exe перестает работать". Вот код новой функции, которая, кажется, вызывает проблему.
void BigInt::u_basic_mult(const BigInt& n, int digs)
{
const base_int* tptr = n.used > used ? n.data : data;
const base_int* bptr = tptr == data ? n.data : data;
const int tlen = tptr == data ? used : n.used;
const int blen = bptr == data ? used : n.used;
if(digs < 1)
digs = tlen + blen + 1;
base_int* new_data = new base_int[digs];
for(int i = 0; i < digs; ++i)
*new_data++ = 0;
for(int i = 0; i < blen; ++i)
{
int stop_pt = MIN(tlen, digs - i);
overflow_int carry = 0;
overflow_int btmp = bptr[i];
for(int j = 0; j < stop_pt; ++j)
{
overflow_int prod = btmp * tptr[j] + carry;
carry = prod >> BASE_BITS;
overflow_int sum = new_data[i + j] + carry + (prod & MAX_DIG);
carry += sum >> BASE_BITS;
new_data[i + j] = sum;
}
}
//delete[] data; these two lines cause the error
//data = new_data;
used = digs;
alloc = digs;
strip_zeros();
}
Обратите внимание на две строки, которые я прокомментировал. Без них программа выполняет и заканчивает (хотя теперь результат неверен). Что это значит изменить значение указателя или удалить его, что может сделать мою программу этой странной ошибкой? Также я уверен, что данные действительны, так как я использую их в приведенном выше коде.
Также я компилирую с G++ через Netbeans.
После осмотра, кажется, проблема может быть у моего деконструктора. Если я прокомментирую данные delete [] в деконструкторе, кажется, что ошибка исчезла. Я не знаю почему.
BigInt::~BigInt()
{
if(data) delete[] data;
}
for(int i = 0; i < digs; ++i)
*new_data++ = 0;
Этот код модифицирует где new_data
указатель не указывает на, так что она больше не указывает на оригинальный массив при входе в последующий цикл, или сделать что - нибудь с ним по этому вопросу. Указатель, который вы передаете для delete[]
должен указывать на тот же адрес памяти, что и new[]
.
Правильный способ ноль-инициализации массива состоит в том, чтобы сделать это вместо этого:
for(int i = 0; i < digs; ++i)
new_data[i] = 0;
Или, избавитесь от цикла и просто используйте memset()
:
memset(new_data, 0, digs * sizeof(base_int));
Я понял. Мне удалось испортить мой указатель new_data.
for(int i = 0; i < digs; ++i)
*new_data++ = 0;
Я изменил это на это.
for(int i = 0; i < digs; ++i)
new_data[i] = 0;
Вы должны быть очень осторожны при сопоставлении использования новых и удаления. Если вы выделяете что-то, используя форму массива new, вы должны удалить его, используя форму массива delete. Если вы смешиваете и сопоставляете массив и формы без массива, вы получите такие сбои. Вы также никогда не должны удалять то, что не было назначено новым, и вы никогда не должны удалять одно и то же дважды.
Я не могу дать вам более конкретные рекомендации по этой конкретной программе, потому что вы не показываете нам, где указывается указатель с именем data.
delete
наnull
- это нормально, проверка не нужна.std::vector<base_int> data
.