***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[]开发者_如何学Python 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
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.
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.
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.
精彩评论