简体   繁体   中英

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

So I'm writing a dynamic array class and I'm running into issues with (I believe) setting up a temporary array to hold the values, then changing the size of the current array, it throws me the glibc detected free(): invalid next size(fast) error. I realize that this either means I'm writing outside of an array's bounds somewhere, or I'm trying to free memory that I don't have allocated to me, but I can't seem to find where the issue is.. Any help would be greatly appreciated, I've been looking over my code for about 2 hours and can't seem to find a way to fix the issue besides removing the delete statements altogether which isn't much of a solution since that just causes memory leaks. And I'm new to C++ so I apologize for any dumb mistakes/syntax

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

main function

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;
}

This code has multiple problems:

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;

Here are some issues with this code:

delete foo; Once you call delete , the memory is freed. So you can no longer use bar as it points to freed memory.

foo = bar; You just allocated memory and saved the pointer in foo , this line throws away that memory address and sets foo back to what it was.

One way to do the upArray is to allocate the new memory, copy the data across, then free the old memory.

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;

Also note that as you have your own allocated pointers in your member variables, you must create a copy constructor and assignment operator (see Rule Of Three). Otherwise any code that makes a copy of an ArrayList object will copy the pointer, leading to multiple deletes of the same memory.

`ArrayList arr;` will call the constructor 

ArrayList::ArrayList(){
    capacity = 1;   
    numElements = 0;
    foo = new int[1];
    foo[0] = 0;
}

Which is creating foo of size 1. then

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

push_back method can only insert one elemnt(because size is 1). Solution : change the for loop for (int i=1;i<=1;i++) so toString should print only one element.I did't compiled your source code. It's my basic understanding.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM