2016-04-27 2 views
-2

проблема заключается в названии, при отладке прямо перед инструкцией удаления я вижу, что указатель (вектор) в порядке, я даже могу изменить его значения через непосредственное окно VC++ Express2013, но после удалить его выбросить исключение:Исключение исключений примитивных векторных исключений

Unhandled exception at 0x55ACDF62 (msvcp120d.dll) in BTREE.EXE: 0xC0000005: Access violation writing location 0xABABABAB. 

Мой вектор является вектор этого класса:

template<class Key, class Value> 
class Pair{ 
public: 
Pair(){ 
    key = Key(); 
    value = Value(); 
} 

Pair(Key key, Value value){ 
    this->key = key; 
    this->value = value; 
} 

Key key; 
Value value; 
}; 

в шаблонах я использую Int для ключа и станд :: строка для значения, вектор распределяется только по этому методу:

Node(unsigned int max){ 
    nelements = 0; 
    nchilds = 0; 
    /*reserva espaço para os elementos e os nós filhos, cada vetor possui uma espaço adicional reservado*/ 
    elements = new Pair<Key, Value>[max]; 
    childs = new Node<Key, Value>*[max + 1]; 
    this->max = max; 

    for (unsigned int i = 0; i < max + 1; i++) 
     childs[i] = nullptr; 
} 

более сложные операции с использованием этого вектора здесь:

 left->nelements = middle; 
    memcpy(left->elements, elements, sizeof(Pair<Key, Value>) * middle); 
    if (!leaf()){ 
     left->nchilds = middle + 1; 
     memcpy(left->childs, childs, sizeof(Node<Key, Value>*) * left->nchilds); 
    } 

и вот деструктор:

~Node(){ 
    for (unsigned int i = 0; i < nchilds; i++) 
      delete childs[i]; 
    delete[] childs; 
    delete[] elements; 
} 

спасибо за помощь.

+0

Вы пытаетесь устранить одну вещь в разы? Вы можете начать с создания вектора и последующего его удаления. Добавить код до появления ошибки. – Quest

+0

Если реальные типы, используемые для 'Key' или' Value', нетривиальны, использование 'memcpy' является недопустимым, а результат неопределенным. Вместо этого вы можете использовать 'std :: copy'. –

ответ

1

Исключение указывает, что ваш код (или, скорее, CRT) попытался записать в ячейке памяти значение 0xABABABAB. В рамках отладчика Visual Studio устанавливает это значение, чтобы помочь найти ошибки. Это означает:

Used by HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory 

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

Удивительно, что вы используете memcpy для копирования elements - вы должны memcpy только тривиальные типы. Для того, чтобы проверить, является ли это случай использования статического утверждение:

static_assert(std::is_trivially_copyable<Pair<Key, Value>>::value, "must be TriviallyCopyable type"); 

всегда лучше использовать std::copy - он будет использовать memmove для TriviallyCopyable типов, а в противном случае будет копировать элементы один за другим.

Чтобы избежать таких ошибок, вы должны использовать std::vector вместо динамических массивов, если вам нужны указатели, то вы можете использовать std::unique_ptr. В сочетании с различными функциями от заголовка <algorithm>.

+0

спасибо за помощь, изменение memcpy с помощью std :: copy действительно сработало, спасибо за советы тоже. – user2542813

0

Я вижу, что вы копируете выделенную память.

memcpy(left->elements, elements, sizeof(Pair<Key, Value>) * middle); 
    if (!leaf()){ 
     left->nchilds = middle + 1; 
     memcpy(left->childs, childs, sizeof(Node<Key, Value>*) * left->nchilds); 
    } 

От Node экземпляра к другому?

В этом случае вы уверены, что освободите выделенный указатель только один раз?

Смежные вопросы