Обнаружено повреждение кучи - PullRequest
0 голосов
/ 28 марта 2011

Единственное, что неверно в выводе моей программы, это то, что есть '!'после «рыбалки».Я пытался отладить его, но никогда не было '!'в памяти.

Вот вывод этой строки

One more: gone down to the fishing! hole

Вот создание s6 и s7

MyString s6("gone ");
MyString s7("fishing");

Вот строка, которая производит оператор

cout << "One more: " << s6 + "down to the " + s7 + " hole" << endl << endl;

Вот функция << перегрузки оператора </p>

ostream& operator<<(ostream& leftOp, const MyString& rightOp)
{
leftOp << rightOp.stringArray;

return leftOp;
}

Вот функция перегрузки оператора +

MyString MyString::operator+(const char* rightOp) const
{
    MyString result; // new object used to store result
    result.stringSize = stringSize + strlen(rightOp);
    // if the string does not fit in the array
    if( result.stringSize > result.stringCap )
    {
        delete[] result.stringArray;
        result.stringCap = ( stringSize + 15 ) & ~15;
        result.stringArray = new char[stringCap + 1];
    }
    strcpy(result.stringArray, stringArray);
    strcat(result.stringArray, rightOp);
    return result;
}

s7 больше нигде в программе не вызывается, поэтому яНе думайте, что больше нет кода, который нужно показывать.Любая помощь будет высоко ценится.

Ответы [ 4 ]

3 голосов
/ 28 марта 2011

Трудно сказать, здесь ли проблема с вашим кодом.
Я бы посмотрел на других участников. Повиновались ли вы правилу 3 ?

Примечание:

Я бы отметил, что вы нарушаете фундаментальное правило ОО.

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

Код был бы чище, если бы вы написали его как:

MyString MyString::operator+(const char* rightOp) const
{
    MyString result(*this);   // make a copy of this.
    result += rightOp;        // Let result fiddle with its own members here.
    return result;
}

Edit:

на основе комментария ниже.

Правило трех

В основном: если ваш объект владеет динамически выделяемой памятью (то есть он вызывает new / delete), то версия методов по умолчанию, сгенерированная компилятором, не будет работать так, как вы хотите; и вы должны определить свои собственные версии:

В основном:

* Copy Constructor
* Assignment Operator
* Destructor

* Not part of rule of 3, but you probably also need a normal constructor.

Самое простое - у вас, вероятно, уже есть деструктор (иначе не было бы повреждения), и оператор присваивания можно записать в терминах конструктора копирования. Поэтому все, что вам нужно сделать, это написать правильную версию конструктора копирования, и все должно работать.

/*
 * Assignment operator using Copy and swap Idiom.
 * Copy uses copy constructor (here done in pass by value)
 *
 * You then just swap the current content with the copy
 */
MyString& MyString::operator=(MyString rhs)
{
    (*this).swap(rhs);
    return *this;
}
1 голос
/ 28 марта 2011

Если вы размещаете stringCap в своем массиве, вы не возражаете против '\ 0'? Символ *, хранящий строку, должен быть массивом размером size-of-string + 1

Возможно, проблема в том, что вы объединяете две строки MyString. Вторая строка, рыболовная, может иметь слишком большое значение stringSize.

И вместо result.stringCap = ( stringSize + 15 ) & ~15; почему бы просто не написать:

result.stringCap = result.stringSize + 1;
0 голосов
/ 28 марта 2011

if( result.stringSize > result.stringCap ) должно быть if( result.stringSize >= result.stringCap ), чтобы разрешить нулевое завершение.Вам также необходимо сбросить result.stringSize.

0 голосов
/ 28 марта 2011

Вы не выделили stringArray в обычном случае, и вы не сбросили stringSize в слишком большом случае, а strncpy безопаснее:

MyString MyString::operator+(const char* rightOp) const
{
    MyString result; // new object used to store result
    result.stringSize = stringSize + strlen(rightOp);
    // if the string does not fit in the array
    if( result.stringSize > result.stringCap )
    {
        delete[] result.stringArray;
        result.stringCap = ( stringSize + 15 ) & ~15;
        // don't allocate here
        result.stringSize = stringCap;
    }

    // always allocate for the new string
    result.stringArray = new char[result.stringSize + 1];

    strncpy(result.stringArray, stringArray, result.stringSize);
    strncat(result.stringArray, rightOp, strlen(rightOp) + 1);
    return result;
}

РЕДАКТИРОВАТЬ : Хорошо, не обращайте на это внимания. Я предположил некоторые вещи о классе MyString, которые, очевидно, не так. Итак, вот что я могу указать сейчас:

if( result.stringSize > result.stringCap )
{
    delete[] result.stringArray;
    result.stringCap = ( stringSize + 15 ) & ~15;
    result.stringArray = new char[stringCap + 1]; // WRONG stringCap!
    result.stringArray = new char[result.stringCap + 1]; // right stringCap
}

И вы можете попробовать упростить вещи, чтобы сузить проблему:

cout << "One more: " << s6 + "down to the " << s7 + " hole" << endl << endl;

возможно проблема в operator+(const MyString&) вместо operator+(const char*)?

...