简体   繁体   中英

***glibc detected*** free(): invalid pointer:

I get the error in the title when I try to run my code... here's what I'm running

class MyQueue {
    tile* queue;
    int size;
public:
    MyQueue(int cap);
    ~MyQueue();
    void enqueue(tile t);
    tile dequeue();
    bool isEmpty();
};

void MyQueue::enqueue(tile t) {
queue[size] = t;
size++;
}

tile MyQueue::dequeue() {
tile temp = queue[0];
tile* victim = queue;
queue++;
delete victim;
return temp;
}

bool MyQueue::isEmpty() {
if (size == 0)
    return true;
else
    return false;
}

MyQueue::MyQueue(int cap) {
queue = new tile[cap];
size = 0;
}

MyQueue::~MyQueue() {
delete[] queue;
}

int main(int argc, char *argv[]) {
tile tile1; tile1.type = '1';
tile tile2; tile2.type = '2';
tile tile3;

MyQueue q(10);
q.enqueue(tile1);
q.enqueue(tile2);
tile3 = q.dequeue();
cout<<tile3.type<<" =1?"<<endl;
return 0;
}

valgrind:

==4506== Mismatched free() / delete / delete []
==4506==    at 0x4C27FFF: operator delete(void*) (vg_replace_malloc.c:387)
==4506==    by 0x400CD2: MyQueue::dequeue() (MyQueue.h:37)
==4506==    by 0x400DD7: main (p1.cpp:24)
==4506==  Address 0x5964040 is 0 bytes inside a block of size 120 alloc'd
==4506==    at 0x4C28658: operator new[](unsigned long) (vg_replace_malloc.c:305)
==4506==    by 0x400D35: MyQueue::MyQueue(int) (MyQueue.h:49)
==4506==    by 0x400D9F: main (p1.cpp:21)
==4506== 
1 =1?
==4506== Invalid free() / delete / delete[]
==4506==    at 0x4C27C7B: operator delete[](void*) (vg_replace_malloc.c:409)
==4506==    by 0x400D74: MyQueue::~MyQueue() (MyQueue.h:54)
==4506==    by 0x400E2F: main (p1.cpp:21)
==4506==  Address 0x596404c is 12 bytes inside a block of size 120 free'd
==4506==    at 0x4C27FFF: operator delete(void*) (vg_replace_malloc.c:387)
==4506==    by 0x400CD2: MyQueue::dequeue() (MyQueue.h:37)
==4506==    by 0x400DD7: main (p1.cpp:24)
==4506== 
==4506== 
==4506== HEAP SUMMARY:
==4506==     in use at exit: 0 bytes in 0 blocks
==4506==   total heap usage: 1 allocs, 2 frees, 120 bytes allocated
==4506== 
==4506== All heap blocks were freed -- no leaks are possible
==4506== 
==4506== For counts of detected and suppressed errors, rerun with: -v
==4506== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 4 from 4)

seems like something stupid but I can't figure it out for the life of me, thanks for the help

This is suspect:

tile MyQueue::dequeue()
{ 
    tile temp = queue[0]; 
    tile* victim = queue; 
    queue++; // <----- Note this!
    delete victim; 
    return temp; 
} 

Calling this function will increment the queue pointer. This causes the pointer you got from new[] to be different than the one you passed to delete[] . Passing a pointer to delete[] that is different from the one that was returned by new[] yields undefined behavior.

Not to mention that you're trying to delete individual tile s with delete victim line. You can't delete individual items in an array allocated with new[] , the only way to delete items is to delete the entire array in one go.

int main(int argc, char *argv[])
{ 
    tile tile1; tile1.type = '1'; 
    tile tile2; tile2.type = '2'; 
    tile tile3; 

    MyQueue q(10); // calls new[] and assigns pointer to queue.
    q.enqueue(tile1); 
    q.enqueue(tile2); 
    tile3 = q.dequeue(); // **increments queue**
    cout<<tile3.type<<" =1?"<<endl; 
    return 0; 
    // When MyQueue is destroyed, its destructor passes new value of
    // queue to delete[], which of course doesn't work.
} 

Unless this is for homework, you really should be using std::queue instead. It's fully tested and part of the C++ standard library. Also, please pick up a good introductory C++ book . Your question demonstrates quite a fundamental misunderstanding of how memory management works.

The problem might be due to the fact that in the constructor you're dynamically allocating an array:

queue = new tile[cap]; 

but in deque you delete it using the non-array delete operator.

tile* victim = queue;
queue++;
delete victim;  

It just looks like the logic in the code is mismatched. On one hand there is code that allocates dynamic arrays but then in other places it deletes individual elements of that dynamically allocated array.

You didn't allocate the original tile you pushed on so you shouldn't deallocate it either in this function. You already handle the total array deallocation in the destructor which is fine.

tile MyQueue::dequeue()
{ 
    assert( size != 0 ); // could throw an exception here
    tile temp = queue[size-1];
    --size;
    return temp;
}

Also in enqueue you don't check if you will add an element past the size of your allocated array so another assert/exception should be put there.

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