使用 const_iterator 成员调用 class 的析构函数时堆损坏
Heap corruption when calling destructor of class with const_iterator member
我有一个 class,其中包含一个字符串双端队列和一个迭代器作为成员。
有一个 GetNext()
方法可以给我下一个元素并递增迭代器。使用外部的 class 我检查一个空字符串以指示双端队列的结尾。
不幸的是,当调用构造函数并且使用 GetNext 获取最后一个元素时,我遇到了堆损坏。
我想发生这种情况是因为在双端队列中的最后一个字符串(空字符串)之后,迭代器仍然递增并指向内存中的某处?
以便析构函数然后尝试释放此内存然后崩溃?
#include <iostream>
#include <string>
#include <deque>
class Foo
{
public:
Foo()
{
list.push_back("first elm");
list.push_back("second elm");
list.push_back(std::string());
pNextItem = list.begin();
}
virtual ~Foo(){}
const std::string& GetNext() { return *pNextItem++; }
protected:
std::deque<std::string> list;
std::deque<std::string>::const_iterator pNextItem;
};
int main()
{
{
Foo foo;
std::cout << foo.GetNext() << std::endl; // "first elm"
std::cout << foo.GetNext() << std::endl; // "second elm"
std::cout << foo.GetNext() << std::endl; // ""
//third call sets the iterator past the last element and causes a segfault
std::cout << foo.GetNext() << std::endl;
}
}
您需要在取消引用之前检查 pNextItem
是否等于 list.cend()
。这正是在第三次调用 foo.GetNext()
之后发生的情况,此时您将取消引用最后一个元素并递增迭代器。
来自 deque::end
reference:
Returns an iterator to the element following the last element of the
container.
This element acts as a placeholder; attempting to access it results in
undefined behavior.
我有一个 class,其中包含一个字符串双端队列和一个迭代器作为成员。
有一个 GetNext()
方法可以给我下一个元素并递增迭代器。使用外部的 class 我检查一个空字符串以指示双端队列的结尾。
不幸的是,当调用构造函数并且使用 GetNext 获取最后一个元素时,我遇到了堆损坏。
我想发生这种情况是因为在双端队列中的最后一个字符串(空字符串)之后,迭代器仍然递增并指向内存中的某处?
以便析构函数然后尝试释放此内存然后崩溃?
#include <iostream>
#include <string>
#include <deque>
class Foo
{
public:
Foo()
{
list.push_back("first elm");
list.push_back("second elm");
list.push_back(std::string());
pNextItem = list.begin();
}
virtual ~Foo(){}
const std::string& GetNext() { return *pNextItem++; }
protected:
std::deque<std::string> list;
std::deque<std::string>::const_iterator pNextItem;
};
int main()
{
{
Foo foo;
std::cout << foo.GetNext() << std::endl; // "first elm"
std::cout << foo.GetNext() << std::endl; // "second elm"
std::cout << foo.GetNext() << std::endl; // ""
//third call sets the iterator past the last element and causes a segfault
std::cout << foo.GetNext() << std::endl;
}
}
您需要在取消引用之前检查 pNextItem
是否等于 list.cend()
。这正是在第三次调用 foo.GetNext()
之后发生的情况,此时您将取消引用最后一个元素并递增迭代器。
来自 deque::end
reference:
Returns an iterator to the element following the last element of the container.
This element acts as a placeholder; attempting to access it results in undefined behavior.