Ошибка утверждения отладки! Манипуляции со строками с использованием арифметики указателей

EDIT: Pastebin ссылается на весь код внизу

для моего курса CS215 мне дали класс под названием String215, который является базовым классом строк, чтобы помочь в понимании динамического распределения памяти и арифметики указателя с массивами символов.

Класс был предоставлен мне в очень простой скелетной форме с прототипами, но без реализаций, а также с тестовой функцией для проверки моих реализаций. Я НЕ МОГУ использовать какие-либо функции C String в этом задании.

Часть программы, которая вызывает беспокойство, — это функция добавления, которая просто добавляет объект строки параметра string215 в конец текущего объекта string215.

// Add a suffix to the end of this string.  Allocates and frees memory.
void string215::append(const string215 &suffix)
{
    char *output = new char[str_len(data)+suffix.length()+1];
    for(int x = 0; x < str_len(data); x++) {
            *output = *data;
        output++;
        data++;
    }

    for(int x = 0; x < suffix.length(); x++) {
        *output = suffix.getchar(x);
        output++;
    }
    *output = '\0';
    output -= (str_len(data)+suffix.length()+1);
    delete[] data;
    data = output;
}

Эта часть кода тестируется в 13-м тесте тестовой функции, как показано здесь:

string215 str("testing");

...

// Test 13: test that append works in a simple case.
curr_test++;
string215 suffix("123");
str.append(suffix);
if (strcmp(str.c_str(), "testing123") != 0) {
    cerr << "Test " << curr_test << " failed." << endl;
    failed++;
}

Вот описание класса добавления:

Добавьте суффикс в конец этой строки. Выделяет новый, больший массив; копирует старое содержимое, за которым следует суффикс, в новый массив; затем освобождает старый массив и обновляет указатель на новый.

Моя программа прерывается в самом конце выполнения функции добавления с сообщением об ошибке:

Debug Assertion Failed!

Program: [Source path]\dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

...

Abort || Retry || Ignore

Я почти уверен, что это как-то связано с моим очень плохим управлением памятью. Я знаю, что это не так много, но я боролся с этим часами подряд и, похоже, не могу понять это.

Вот вставка файла .cpp и .h для этой программы

string215.cpp: http://pastebin.com/Xh2SvDKJ

string215.h: http://pastebin.com/JfAJDEVN

Любая помощь очень ценится!

Спасибо, RAW-BERRY


person user2125518    schedule 02.03.2013    source источник


Ответы (3)


Вы меняете указатель data перед delete[]. Вам нужно delete[] точно такое же значение, которое вы получили от new[].

Кроме того, вы увеличиваете output указатель str_len(data)+suffix.length() раз и забираете его обратно на str_len(data) + suffix.length() + 1.

Я бы использовал отдельные переменные для итерации, чтобы решить эти проблемы.

person zch    schedule 02.03.2013
comment
Аааа, это имеет смысл! Проверка локальных переменных во время выполнения функции добавления подтверждает, что вывод содержит правильное значение, так что это хорошо! Однако теперь я получаю сообщение об ошибке HEAP CORRUPTION DETECTED, что, насколько я могу судить, обычно означает, что я неправильно распределил память? Нужно ли перераспределять память для данных? Мне просто сделать новый пост? - person user2125518; 02.03.2013

Вы увеличиваете output ровно str_len(data) + suffix.length() раза. Обратите внимание, что вы не увеличиваете output после *output = '\0';.

Итак, чтобы вернуться к началу, вы должны использовать:

output -= (str_len(data) + suffix.length());

Кстати, часть кода не очень эффективна. Например, getchar использует цикл вместо простого возврата data[index]. Вы используете getchar в append, что означает, что производительность не велика.

EDIT: Как говорит zch, вы используете delete[] data после изменения data, но обратите внимание, что даже до этого вы используете str_len(data) после изменения data (при принятии решения о том, сколько байтов нужно пропустить), поэтому расчет неверен ( и мое предложение выше тоже неверно, потому что str_len(data) теперь равно нулю).

person Omri Barel    schedule 02.03.2013
comment
Потрясающе спасибо! Я разобрался со своей первоначальной проблемой, теперь дело за следующей! Куча порчи T_T - person user2125518; 02.03.2013

Так что я думаю, что ваша проблема с линией

for(int x = 0; x < str_len(data); x++) {

Обратите внимание, что размер «данных» меняется на каждой итерации цикла. Когда вы увеличиваете «x», вы уменьшаете длину «данных». Предположим, что «данные» — это строка, содержащая «привет»: в первой итерации цикла x=0 и str_len(data)=5; во второй итерации x=1 и str_len(data)=4. Таким образом, цикл for выполняется в два раза меньше, чем вам нужно, а «данные» не указывают на конец строки данных.

person dani    schedule 02.03.2013