删除 xmemory0 中的 HashMap 元素时出错
Error when deleting HashMap Element in xmemory0
每当我尝试为我的 HashMap 删除一个元素时,我都会在 C++ 代码中遇到一个错误(不是我的代码......C++ 人的代码 - 特别是 xmemory0)。我确定错误在我这边,但我不知道在哪里,因为调试器告诉我它在别处。我的 HashMap 已经过全面测试,除了我尝试删除 HashElement 时,它似乎运行良好。我很确定在删除 HashElement 之前没有任何内容指向它(我认为这是第一个猜测)。谁能告诉我为什么在尝试删除 HashElement 时出现错误?这是我的堆栈跟踪:
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_;
}
我也很乐意 post HashMap 本身,但我不认为该错误与实际的 HashMap 代码有关,所以我暂时将其搁置 post 更具可读性。
编辑:
刚刚发现这个错误确实存在于我的 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_;
}
我得到了外界的帮助,然后@leewangzhong 在评论中得到了帮助。问题出在 HashMap.cpp
的 Remove()
方法中。我确实有一个悬空指针。这是更正的方法:
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_--;
}
每当我尝试为我的 HashMap 删除一个元素时,我都会在 C++ 代码中遇到一个错误(不是我的代码......C++ 人的代码 - 特别是 xmemory0)。我确定错误在我这边,但我不知道在哪里,因为调试器告诉我它在别处。我的 HashMap 已经过全面测试,除了我尝试删除 HashElement 时,它似乎运行良好。我很确定在删除 HashElement 之前没有任何内容指向它(我认为这是第一个猜测)。谁能告诉我为什么在尝试删除 HashElement 时出现错误?这是我的堆栈跟踪:
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_;
}
我也很乐意 post HashMap 本身,但我不认为该错误与实际的 HashMap 代码有关,所以我暂时将其搁置 post 更具可读性。
编辑:
刚刚发现这个错误确实存在于我的 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_;
}
我得到了外界的帮助,然后@leewangzhong 在评论中得到了帮助。问题出在 HashMap.cpp
的 Remove()
方法中。我确实有一个悬空指针。这是更正的方法:
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_--;
}