错误glibc检测到free():无效的下一个大小(fast)

Error glibc detected free(): invalid next size(fast)

本文关键字:下一个 fast 无效 free glibc 错误 检测      更新时间:2023-10-16

所以我正在写一个动态数组类,我遇到了(我相信)设置一个临时数组来保存值,然后更改当前数组的大小的问题,这会导致glibc检测到的free():无效的下一个大小(快速)错误。我意识到,这要么意味着我在某个数组的边界之外写作,要么我试图释放没有分配给我的内存,但我似乎找不到问题所在。如果有任何帮助,我们将不胜感激,我已经查看了大约2个小时的代码,除了完全删除delete语句之外,似乎找不到解决问题的方法,这不是一个很好的解决方案,因为这只会导致内存泄漏。我是C++的新手,所以我为任何愚蠢的错误/语法道歉

ArrayList.cpp

#include "ArrayList.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int& ArrayList::operator[](unsigned int i){
    return foo[i];
}
int ArrayList::size(){
    return numElements;
}
void ArrayList::downArray(){
    int* bar = foo; //temp array to hold values while I decrease the size
    capacity /= 2;
    delete foo;
    foo = new int[capacity]; //don't I lose the original pointer here? So why does it throw an error when I try to delete foo, as if I haven't allocated that memory?
    for(int i = 0; i < capacity;i++){
        foo[i] = bar[i];    
    }
}
void ArrayList::upArray(){
    int* bar = foo; //temp array to hold values while I increase the size
    delete foo;
    foo = new int[capacity*2]; //same thing here
    foo = bar;
    for(int i = capacity; i < capacity*2;i++){
        foo[i] = 0;
    }
    capacity *=2;
}
void ArrayList::push_back(int m){
    if(numElements == capacity) //full, double foo
        upArray();
    foo[numElements] = m;
    numElements++;
}
void ArrayList::erase(int m){
    bool notFound = true;   
    int i = 0;
    while(notFound)
        if(foo[i] == m){
            notFound = false;    //Ha! Found you!
            for(int j = i; j+1 < capacity; j++){
                foo[j] = foo[j+1]; //moves everything to right of m one spot left
            }
        }
        else
            i++; //keep looking
}
string ArrayList::toString(){
    stringstream sobj;
    string x;
    sobj << "[";
    for(int i = 0; i < numElements; i++){
        if(i == numElements-1) //last iteration, avoids output displaying [1,2,3,4,]
            sobj << foo[i];
        else
            sobj << foo[i] << ",";
    }
    sobj << "]";
    sobj >> x;
    return x;
}
ArrayList::ArrayList(){
    capacity = 1;   
    numElements = 0;
    foo = new int[1];
    foo[0] = 0;
}
ArrayList::~ArrayList(){
    //delete foo; //is this not the proper place to call it?
    cout << "Destructor called" << endl;
}

ArrayList.h

#ifndef _ARRAYLIST_H_
#define _ARRAYLIST_H_
#include <string>
class ArrayList
{
 public:
    ArrayList();
    ~ArrayList();
    int& operator[](unsigned int i); // int& ArrayList::operator[](unsigned int i){....}
    void push_back(int m); 
    void erase(int m);
    std::string toString();
    int size();
 private: 
  void downArray();
    void upArray();
 private:
  int capacity, numElements;
    int* foo;
};
#endif

主要功能

int main(int argc,char *argv[])
{
    ArrayList arr;
    for (int i=1;i<=50;i++)
    {
        arr.push_back(i);
    }
    cout << "Should contain numbers 1..50, is ";
    cout << arr.toString() << endl;
}

此代码有多个问题:

int* bar = foo; //temp array to hold values while I increase the size
delete foo;
foo = new int[capacity*2]; //same thing here
foo = bar;
for(int i = capacity; i < capacity*2;i++){
    foo[i] = 0;
}
capacity *=2;

以下是此代码的一些问题:

delete foo;调用delete后,内存将被释放。因此,不能再使用bar,因为它指向释放的内存。

foo = bar;您刚刚分配了内存并将指针保存在foo中,这一行丢弃了内存地址并将foo设置回原来的状态。

执行upArray的一种方法是分配新内存,复制数据,然后释放旧内存。

int* bar = new int[capacity*2]; // new array to hold values
// Copy the data
for(int i = 0; i < capacity;i++){
    bar[i] = foo[i];
}
// Zero out the rest
for(int i = capacity; i < capacity*2;i++){
    bar[i] = 0;
}
delete foo;  // delete the old memory
foo = bar;   // point to the new memory.
capacity *=2;

还要注意的是,由于在成员变量中有自己分配的指针,因此必须创建一个复制构造函数和赋值运算符(请参见三条规则)。否则,任何复制ArrayList对象的代码都会复制指针,导致同一内存被多次删除。

`ArrayList arr;` will call the constructor 
ArrayList::ArrayList(){
    capacity = 1;   
    numElements = 0;
    foo = new int[1];
    foo[0] = 0;
}

它正在创建大小为1的foo。然后

 for (int i=1;i<=50;i++)
    {
        arr.push_back(i);
    }

pushback方法只能插入一个elemnt(因为大小是1)。解决方案:更改for循环for (int i=1;i<=1;i++),使toString只打印一个元素。我没有编译你的源代码。这是我的基本理解。