Возврат копии с перегруженными операторами - PullRequest
5 голосов
/ 04 марта 2011

У меня есть класс Foo, для которого я перегружен оператор + следующим образом:

Foo Foo::operator+(const Bar &b)
{
    Foo copy = (*this);
    if (someCondition) return copy;
    //snip
}

Для меня это выглядит разумно. Однако всякий раз, когда я возвращаю копию, Visual Studio предупреждает меня об ошибке, которая «может быть связана с повреждением кучи». Что-то не так с тем, что я сделал?

edit: обновление с дополнительной информацией.

Сообщение об ошибке:

Windows запустила точку останова в SAMPLE.EXE.

Это может быть связано с повреждением куча, которая указывает на ошибку в sample.exe или любую из имеющихся библиотек загружен.

Это также может быть связано с пользователем нажатие F12 в то время как sample.exe имеет фокус.

Окно вывода может иметь больше диагностическая информация.

Конструктор копирования:

Foo::Foo(const Foo&p)
{
    some_pointer = p.get_some_pointer();
    some_value = p.get_some_value();
}

Код, который он разбивает на:

//within dbgheap.c
    extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
            const void * pUserData
            )
    {
            if (!pUserData)
                return FALSE;

            if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
                return FALSE;

            return HeapValidate( _crtheap, 0, pHdr(pUserData) );
    }

1 Ответ

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

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

Первое, что я хотел бы сделать, это посмотреть деструкторы и убедиться, что вы не копируете и не удаляете их вдвойне. Например, со следующим кодом:

// buggy!!!
struct test {
    int * data;
    test() : data( new int[5] ) {}
    ~test() { delete [] data; }
    test( test const & rhs ) : data( rhs.data ) {}
    test& operator=( test const & rhs ) {
       data = rhs.data;
    }
};
int main() {
    test t1;          // 5 ints allocated int t1.data
    test t2( t1 );    // no memory allocated, t2.data == t1.data
} // t2 out of scope: t2.~test() => delete t2.data
  // t1 out of scope: t1.~test() => delete t1.data but both are the same: double delete

Если это так, вы можете решить, хотите ли вы иметь мелкие копии или делать глубокие копии. Во втором случае конструктор копирования (и оператор присваивания) должен выделить свою собственную память, а во втором случае вы должны убедиться, что память не освобождается дважды.

Как всегда с указателями, лучше делегировать управление ресурсами внешним (предварительно созданным) классам. В случае уникального владельца (и глубоких копий) вам, вероятно, следует использовать std::auto_ptr (или std::unique_ptr в C ++ 0x - или варианты наддува). Во втором случае использование boost::shared_ptr (или std::shared_ptr в C ++ 0x) обеспечит общий доступ к данным и их удаление только один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...