2015-03-02 3 views
0

Всякий раз, когда я пытаюсь удалить один элемент для моего HashMap, я получаю сообщение об ошибке в коде C++ (а не в моем коде ... код C++ people - в частности, xmemory0). Я уверен, что ошибка на моем конце, но я не знаю, где, поскольку отладчик говорит мне ее в другом месте. Мой HashMap был тщательно протестирован и, кажется, работает нормально, за исключением тех случаев, когда я пытаюсь удалить HashElement. Я почти уверен, что ничто не указывает на HashElement, прежде чем я удалю его (что, я думаю, будет первым предположением). Может кто-нибудь сказать, почему я получаю сообщение об ошибке, когда пытаюсь удалить HashElement? Вот мой трассировки стека:Ошибка при удалении элемента HashMap в xmemory0

msvcr120d.dll!operator delete(void *) Unknown 
> MyProgram.exe!std::allocator<char>::deallocate(char * _Ptr, unsigned int __formal) Line 573 C++ 
    MyProgram.exe!std::_Wrap_alloc<std::allocator<char> >::deallocate(char * _Ptr, unsigned int _Count) Line 859 C++ 
    MyProgram.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(bool _Built, unsigned int _Newsize) Line 2284 C++ 
    MyProgram.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >() Line 992 C++ 
    MyProgram.exe!HashElement::~HashElement() Line 12 C++ 

Вот код:

HashElement.h

#pragma once 

#include <string> 

class HashElement 
{ 
private: 
    int key_; 
    std::string value_; 
public: 
    HashElement(int, std::string); 
    ~HashElement(); 
    HashElement *next_element_; 
    int GetKey(); 
    std::string GetValue(); 
}; 

HashElement.cpp

#include "HashElement.h" 

HashElement::HashElement(int key, std::string value) 
{ 
    key_ = key; 
    value_ = value; 
    next_element_ = nullptr; 
} 

HashElement::~HashElement() 
{ 
} //This is the last line before it goes off into not my code 

int HashElement::GetKey(){ 
    return key_; 
} 

std::string HashElement::GetValue(){ 
    return value_; 
} 

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

EDIT:

Просто обнаружил, что ошибка на самом деле лежит в моей HashMap. Не знаю, где. Я так думаю, потому что простое создание и удаление HashElement не воспроизводило ошибку. Но вот код:

HashMap.h

#pragma once 
#include <string> 

#include "HashElement.h" 

class HashMap 
{ 
private: 
    HashElement **map_; 
    int size_; 
    int count_; 
public: 
    HashMap(int); 
    ~HashMap(); 
    int GetHash(int); 
    void Put(int, std::string); 
    std::string GetElement(int); 
    bool Contains(int); 
    void Remove(int); 
    int GetCount(); 
}; 

HashMap.cpp

#include "HashMap.h" 

HashMap::HashMap(int size) 
{ 
    size_ = size; 
    map_ = new HashElement*[size_](); 
} 

HashMap::~HashMap() 
{ 
    for (int i = 0; i < size_; i++){ 
     int hash = GetHash(i); 
     if (!map_[hash]){ 
      continue; 
     } 
     HashElement *currentElement = map_[hash]; 
     HashElement *nextElement = map_[hash]; 
     while (nextElement->next_element_){ 
      nextElement = nextElement->next_element_; 
      delete currentElement; 
      currentElement = nextElement; 
     } 
     delete currentElement; 
    } 
} 

int HashMap::GetHash(int key){ 
    return key % size_; 
} 

void HashMap::Put(int key, std::string value){ 
    int hash = GetHash(key); 
    if (!map_[hash]){ 
     map_[hash] = new HashElement(key, value); 
    } 
    else{ 
     HashElement *lastElement = map_[hash]; 
     while (lastElement->next_element_){ 
      lastElement = lastElement->next_element_; 
     } 
     lastElement->next_element_ = new HashElement(key, value); 
    } 
    count_++; 
} 

std::string HashMap::GetElement(int key){ 
    int hash = GetHash(key); 
    if (map_[hash]){ 
     HashElement *currentElement = map_[hash]; 
     while (currentElement->GetKey() != key && currentElement->next_element_){ 
      currentElement = currentElement->next_element_; 
     } 
     return currentElement->GetValue(); 
    } 
    return nullptr; 
} 

bool HashMap::Contains(int key){ 
    int hash = GetHash(key); 
    if (map_[hash]){ 
     HashElement *currentElement = map_[hash]; 
     while (currentElement->GetKey() != key && currentElement->next_element_){ 
      currentElement = currentElement->next_element_; 
     } 
     if (currentElement->GetKey() == key){ 
      return true; 
     } 
    } 
    return false; 
} 

void HashMap::Remove(int key){ 
    if (!Contains(key)){ 
     return; 
    } 
    int hash = GetHash(key); 
    HashElement *currentElement = map_[hash]; 
    if (!currentElement->GetKey() == key){ 
     HashElement *previousElement = currentElement; 
     currentElement = currentElement->next_element_; 
     while (currentElement->GetKey() != key){ 
      previousElement = currentElement; 
      currentElement = currentElement->next_element_; 
     } 
     if (currentElement->next_element_){ 
      previousElement->next_element_ = currentElement->next_element_; 
     } 
    } 
    delete currentElement; 
    count_--; 
} 

int HashMap::GetCount(){ 
    return count_; 
} 
+0

Это настоящий проект или домашнее задание? Потому что вы должны использовать векторы и интеллектуальные указатели вместо new/delete, и я уверен, что проблемы просто исчезнут. –

+0

Это вещь портфолио. Я намеренно не использую интеллектуальные указатели. Если бы это была настоящая вещь, я был бы C# -в ее :-) – Evorlor

+0

Я не знаю, что означает «портфолио». –

ответ

0

я получил помощь извне, а затем помочь с @leewangzhong в комментариях. Вопрос был в методе Remove() от HashMap.cpp. У меня действительно был висящий указатель. Вот скорректированный метод:

void HashMap::Remove(int key){ 
    if (!Contains(key)){ 
     return; 
    } 
    int hash = GetHash(key); 
    HashElement *currentElement = map_[hash]; 
    if (currentElement->GetKey() == key){ 
     delete currentElement; 
     map_[hash] = nullptr; 
    } 
    else{ 
     HashElement *previousElement = currentElement; 
     currentElement = currentElement->next_element_; 
     while (currentElement->GetKey() != key){ 
      previousElement = currentElement; 
      currentElement = currentElement->next_element_; 
     } 
     previousElement->next_element_ = currentElement->next_element_; 
     delete currentElement; 
    } 
    count_--; 
} 
+1

У вас все еще будет висячий указатель. Удалите проверку для 'if (currentElement-> next_element_)', так что, если она равна null, 'previousElement-> next_element_' будет правильно установлен в значение null. (Кроме того, вы выполняете два поиска по таблице: один для локализации, другой для удаления. Поиск сдерживания не требуется, если вы подготовитесь к возможности его не содержать элемент.) – leewz

+0

Не является ли эта проверка необходимой, если ключ находится в конечном элементе цепи? – Evorlor

+0

Рассмотрите, что происходит с 'previousElement-> next_element_', если ключ находится в конце цепочки. – leewz

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