free():实现矢量擦除()时的指针无效
free(): invalid pointer when implementing erase() of vector
我正在尝试实现Vector类。首先,我的 Vector 还不支持泛型,只支持我的Thing
类。
Vector 类应该支持:empty()、push_back()、erase() 和下标运算符。如果需要,它还应相应地调整大小。
我的矢量实现:
class Vect {
public:
Vect() {
length = 0;
capacity = 3;
charCnt = 0;
data = new Thing[capacity];
}
~Vect() {
delete[] data;
}
bool empty() const {
return length == 0;
}
void push_back(const char *str) {
if(length + 1 == capacity)
doubleSize();
data[length++] = Thing(str);
charCnt += strlen(str);
}
bool erase(size_t at) {
if(at >= length)
return false;
auto newData = new Thing[capacity];
size_t newIndex = 0;
for(size_t i = 0; i < at; i++)
newData[newIndex++] = data[i];
for(size_t i = at + 1; i < length; i++)
newData[newIndex++] = data[i];
//free(): invalid pointer
delete[] data;
data = newData;
return true;
}
const char* operator[](unsigned int index) {
return data[index].getStr();
}
char* toString() {
auto result = make_shared<char *>(new char[charCnt + 1]);
size_t resultIndex = 0;
for(size_t dataIndex = 0; dataIndex < length; dataIndex++) {
auto patchOffset = data[dataIndex].getO();
auto patchLength = data[dataIndex].getL();
for(size_t patchIndex = patchOffset; patchIndex < patchLength; patchIndex++)
(*result.get())[resultIndex++] = data[dataIndex].getStr()[patchIndex];
}
(*result.get())[resultIndex] = ' ';
return *result.get();
}
private:
size_t length, capacity, charCnt;
Thing *data;
void doubleSize() {
size_t newCapacity = capacity*2;
auto newData = new Thing[newCapacity];
for(size_t i = 0; i < length; i++) {
newData[i] = data[i];
}
//this works
delete[] data;
data = newData;
}
};
当我尝试实施erase()
时,我遇到了问题。我的实现很简单:erase()
接受一个参数,即应该删除元素的索引。所以我创建了一个新数组,将所有内容复制到擦除索引,跳过索引,然后复制其余内容。然后我删除旧数组并将新数组分配给变量。
我在doubleSize()
方法中做了非常相似的事情,似乎工作正常(检查瓦尔格林德)。
我遇到的问题是delete[]
不适用于data
。
我使用的测试环境:
class Thing {
public:
Thing() {
o = 0;
l = 0;
ptr = nullptr;
}
explicit Thing(const char *str) {
ptr = str;
o = 0;
l = strlen(str);
}
Thing(const Thing &other) {
this->o = other.o;
this->l = other.l;
this->ptr = other.ptr;
}
friend void swap(Thing &first, Thing &other) {
using std::swap;
swap(first.o, other.o);
swap(first.l, other.l);
swap(first.ptr, other.ptr);
}
Thing& operator=(Thing other) {
swap(*this, other);
return *this;
}
Thing(Thing &&other) noexcept: Thing() {
swap(*this, other);
}
size_t getO() const {
return o;
}
size_t getL() const {
return l;
}
const char* getStr() const {
return ptr;
}
private:
size_t o, l;
const char *ptr;
};
//class Vect...
int main() {
Vect s; char tmpStr[100];
assert(s.empty());
s.push_back("hello ");
s.push_back("world");
s.push_back("!");
s.push_back(" this ");
s.push_back("is ");
s.push_back("me!");
strncpy(tmpStr, "hello world! this is me!", sizeof(tmpStr));
assert(stringMatch(s.toString(), tmpStr));
s.erase(2);
strncpy(tmpStr, "hello world this is me!", sizeof(tmpStr));
assert(stringMatch(s.toString(), tmpStr));
}
在咨询调试器后,我发现了以下内容:
就内容而言,第一个循环工作正常。
第二次循环:在第二次迭代之后,在赋值之后 -
data[0]
被损坏 -o
和l
变量获得随机值,而ptr
仍然指向正确的字符串。完成第二个循环的最后一次迭代后,
ptr
现在变为NULL
,data[1]
现在具有随机o
和l
值。
之后delete []
被调用,这将毫不奇怪地触发错误,因为我用分配的内存做了一些狂野的牛仔竞技表演。
我在哪里管理我的记忆不善?
doubleSize
分配新的缓冲区,但不更新capacity
成员。一旦length
过了capacity
,你甚至不再检测到溢出。最终,你会真正溢出。
虽然您使用erase
擦除,这会减小矢量的大小,但不会减少length
变量。
相关文章:
- 引用一个已擦除类型(void*)的指针
- 擦除while循环中迭代的元素
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- C++擦除(如果存在)
- 在映射擦除c++期间执行循环的次数
- 为什么擦除方法会影响结束方法
- C++ 字符串类擦除成员函数的时空复杂性
- 类型擦除的std::function与虚拟函数调用的开销
- C++14 中unordered_map矢量和擦除删除成语的奇怪行为
- C++ 擦除函数中需要澄清
- 在擦除或修改作为不同索引键的值时,boost::multi_index 迭代器是否无效?
- 对文字擦除无效*的引用
- 迭代器擦除矢量中的元素无效,但它不会崩溃
- free():实现矢量擦除()时的指针无效
- 标准::矢量::擦除无效范围
- 调整STL矢量的大小是否会擦除/使其以前的内容无效
- 调用擦除后迭代程序无效
- std::vector::erase()是否在擦除时使迭代器无效
- STL矢量擦除后的迭代器无效
- std容器迭代器在擦除过程中无效