I would like to know why in the following code the first delete won't free the memory:
#include <list>
#include <stdio.h>
struct abc {
long a;
abc() {
puts("const");
}
~abc() {
puts("desc");
}
};
int main() {
std::list<abc*> test;
abc* pA = new abc;
printf("pA: 0x%lX\n", (unsigned long int)pA);
test.push_back(pA);
abc* pB = test.back();
printf("pB: 0x%lX\n", (unsigned long int)pB);
delete pB; // just ~abc()
test.pop_back();
delete pA; // ~abc() and free (works)
puts("before double-free");
delete pA; // ~abc() and second free (crash)
return 0;
}
Output is:
const
pA: 0x93D8008
pB: 0x93D8008
desc
desc
before double-free
desc
*** glibc detected *** ./test: double free or corruption (fasttop): 0x093d8008 ***
...
I tried it with free() also but same behavior.
delete pA; // ~abc() and free (works)
puts("before double-free");
delete pA; // ~abc() and second free (crash)
These delete statements are not needed once you write delete pB. You've a misconception that delete pB only calls the destructor. No, it calls the destructor and also deallocates the memory.
Also, since you've already written delete pB, the next two further delete expressions invoke undefined behavior, which means anything can happen : the program may or may not crash!
Have a look at these topics:
Undefined, unspecified and implementation-defined behavior
Is there any way to predict the undefined behaviour or implementation defined behaviour?
What are all the common undefined behaviours that a C++ programmer should know about?
Your first delete renders the pointer to invalid state. So use of that pointer now leads to undefined behaviour.
int* p = new int;
delete p;
delete p; //undefined behaviour
This is guaranteed to be fine by the standard (as pointed out in the first comment):
int* p = new int;
delete p;
p = 0;
delete p; //fine
First, you can't free memory allocated with new, you have to use delete.
Secondly, just because glibc doesn't detect the double free immediately, how do you know delete pB; isn't freeing it? That's what delete does, and from your own logging you're passing the same address to delete each time.
Thirdly: what are you actually trying to accomplish?
It's just an indiosyncracy of your compiler/platform that you had to call delete twice on pA before glibc complained ... for instance, on my current platform, which is OSX 10.6.8 with gcc version i686-apple-darwin10-gcc-4.2.1, I get the following output:
const
pA: 0x100100080
pB: 0x100100080
desc
desc
test(14410) malloc: *** error for object 0x100100080: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap
So you can see the first call to delete on pA, which by the standard results in undefined behavior since you didn't set the pointer to NULL or 0, did get caught as an attempt to deallocate already deallocated memory by the C++ run-time on my platform.
Since the results of the double-delete are "undefined behavior", it's really up to the implementation and platform on what happens.
You may be able to detect allocation/deallocation memory errors quicker if you use the link against the glibc memory consistency checker by compiling with the -lmcheck flag.
Related
I'm writing my first opencv code(and first C++ code actually), and met with a strange munmap_chunk(): invalid pointer error when I try to use cv::Ptr. I see in other posts that this usually results from freeing a already freed area, but I think I didn't.
The following simple testing function will generate that error.
void testing(void) {
int i=2;
Ptr< Mat > pointer=new Mat[i];
}
From the debugger, it seems that the destructor triggers the error when the function returns.I couldn't figure out why since basically I did nothing with the Ptr. So why this is happening and what's the correct usage?
Thanks in advance.
In C++ there is a significant difference between memory allocated with new and memory allocated with new [].
int* p = new int;
delete p;
p = new int[8];
delete p; // error/crash
delete [] p; // correct
The Ptr class is an RAII container for managing ownership of pointers. When you assign to it, it takes ownership of that allocation, meaning it will delete it when the Ptr goes out of scope (in this case at the end of the function).
It uses delete by default hence your crash, and the documentation suggests you will need to use the constructor that lets you specify you own deleter:
// see http://docs.opencv.org/master/d0/de7/structcv_1_1Ptr.html
void array_deleter(Mat* m)
{
delete [] m;
}
Prt<Mat> ptr(new Mat[i], array_deleter);
I'm writing a backtracking problem for homework, and all the code works except for my delete[] at the end.
/*Assg4.cc*/
int main()
{
//removed irrelevant code - see pastebin links if needed
void *data = &datavector;
bool finished = false;
bool* continuance = &finished;
int *a = new int[n+1];
for(int i=0; i<n; i++)
{
a[i] = NULL;
}
delete []a;
delete continuance;
return 0;
}
I get the following error:
*** glibc detected *** ./Assg4: free(): invalid pointer: 0xbfc7098f ***
The function backtrack() merely fills the contents of the array a[] at some point, it doesn't delete, expand, or shrink the array in any way. I know the problem is with the deletes at the end, because when I comment them out I get no error (and the result of all computations is correct). What am I doing wrong?
Pastebin full files:
Assg4.cc
backtrack.cc & backtrack.h
Pretty sure your error is actually here:
delete continuance;
You're trying to delete something allocated on the stack, since continuance points to finished, which is allocated on the stack (without a call to new). Items on the stack will be destroyed automatically when they go out of scope, so you don't have to worry about deleting continuance.
See: What and where are the stack and heap
bool finished = false;
bool* continuance = &finished;
delete continuance;
You are calling delete on a pointer which is not allocated using new. This is causing an Undefined Behavior.
finished is a automatic/local variable which is autmatically destroyed once the scope { } in which it is declared ends.
The rule is simple:
Don't call delete unless you called new.
After implementing the C++ code below, I ran valgrind --leak-check=full in order to check if there was any memory leak. The result was 0 bytes were in use at exit and no leaks are possible.
However, later I discovered that I've forgotten to use delete[] x instead of just delete x inside the destructor.
I searched for some explanations (for instance: delete vs delete[] operators in C++), and everything I read said that using delete without [] can cause memory leak, since it calls just the destructor for the first object in the array.
I changed the code to delete[] and the valgrind output was the same (as expected). But now I'm confused: "Is there a problem with valgrind, or does delete really works fine for arrays even without the operator []?"
#include <iostream>
#include <string.h>
using namespace std;
class Foo {
private: char *x;
public:
Foo(const char* px) {
this->x = new char[strlen(px)+1];
strcpy(this->x, px);
}
~Foo() {
delete x;
}
void printInfo() { cout << "x: " << x << endl; }
};
int main() {
Foo *objfoo = new Foo("ABC123");
objfoo->printInfo();
delete objfoo;
return 0;
}
using delete without [] causes memory leak.
No, it causes Undefined Behavior.
Your program where you allocate using new [] and deallocate using delete has Undefined Behavior. Actually, you are lucky(rather unlucky) it doesn't show some weird behavior.
As a side note, You also need to follow the Rule of Three for your class. Currently, you don't do so and are calling for trouble in near future.
The main difference between delete and delete[] is not about memory deallocation, but about destructor calls.
While formally undefined behavior, in practice it will more or less work... except that delete will only call the destructor of the first item.
As a side note, you may get an issue:
#include <iostream>
struct A{
~A() { std::cout << "destructor\n"; }
};
int main() {
A* a = new A[10];
delete a;
}
a bit like:
*** glibc detected *** ./prog: munmap_chunk(): invalid pointer: 0x093fe00c ***
======= Backtrace: =========
/lib/libc.so.6[0xb759dfd4]
/lib/libc.so.6[0xb759ef89]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/libstdc++.so.6(_ZdlPv+0x21)[0xb77602d1]
./prog(__gxx_personality_v0+0x18f)[0x8048763]
./prog(__gxx_personality_v0+0x4d)[0x8048621]
======= Memory map: ========
See it at ideone.
I would like to ask if I's correct the following :
MyClass *obj = new MyClass();//allocate memory
obj.Variab="HELLO";
obj=NULL;
delete obj; //free memory
Is the memory allocated for obj deleted after the last two sentences? Appreciate.THX
I would like to mention that I am working in c++ /Ubuntu. G++ is the compiler
EDIT:
What if I have?
int i=0;
list<string>l;
while (i<100)
{
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
//add the obj.valie in a list
l.push_back(obj);
i=i+1;
delete obj; //free memory
}
it is ok?
no, you should use delete before assigning to NULL
delete obj; //free memory
obj=NULL;
this is becasue the actual parameter to delete is the address of the allocated memory, but if you assign NULL before delete is used, you are actually passing NULL to delete, and nothing will happen, and you will get yourself a memory leak.
your edit question:
this code will not compile, as obj is not defined outside the while scope, in any case, also, l is a list<string> and you are trying to insert MyClass* types,this will result in another compilation error. also, you should use obj->Variab and not obj.Variab, since obj is a pointer.
EDIT to EDIT:
well, you still got a compilation error, since obj is not defined when you are trying to delete it. try this:
#include <iostream>
#include <list>
using namespace std;
class MyClass {
public:
string Variab;
};
void myfunction (const string& s) {
cout << " " << s;
}
int main()
{
int i=0;
list<string>l;
while (i<100) {
MyClass *obj = new MyClass();//allocate memory
obj->Variab="HELLO";
l.push_back(obj->Variab);
i=i+1;
delete obj; //free memory
}
for_each (l.begin(), l.end(), myfunction);
}
This not correct:
obj = NULL; // don't do that!
delete obj;
When you assign NULL to obj, you're losing the address it contained before, leaking the memory. When you then delete obj, you are deleting NULL, which is well-defined - as doing nothing.
As others have said,
delete obj;
obj = NULL;
is the common pattern to do that.
However, I consider it an anti-pattern.
Whenever you are tempted to assign NULL to a pointer after deleting its content, ask yourself: Why is this pointer still in scope? Are you sure you still need it?
It's much better to simply let a pointer fall out of scope once it's done.
Whenever you are doing
resource r = acquire();
use(r);
free(r);
(with memory/dynamically allocated objects being the most common resource), alarm bells should go off. What if use(r) fails with an exception?
Never use naked, dumb pointers. Better read about RAII and smart pointers.
This would leak, delete will not clean up what you allocated with new. Change the order:
delete obj;
obj = NULL; // I would avoid this.
Setting obj to null does not free the memory you allocated. The memory becomes no longer assigned to a variable but is still reserved, and results in a memory leak. Calling delete on a null pointer will have no effect. After the memory has been freed, the pointer becomes invalid and it is good practice to assign it to null. You need to switch the order of the last 2 statements:
delete obj; //free memory first
obj=NULL; //Set pointer to null for safety
You have to delete the very same address as was returned by new - so you have to first delete, then set to null.
Setting pointer to null doesn't affect allocation - you just overwrite the address stored in the pointer and can't access the object anymore (which implies you can't delete the object and have it leaked).
UPDATE (SOLVED): All right, I'm a complete idiot! Turns out in the "do stuff with data" part in my main program I ended up incrementing the pointer, so the delete obviously wouldn't work! D'oh!
So I am compiling a shared library that has a function similar to this (super simplified view), and this library is also mine- so I know how data is allocated:
// inside library
void* getData(int size) { // with other parameters
UINT8* data = new UINT8[size]; // where typedef uint8_t UINT8; for gcc
// do a socket read, where data is the buffer
blockingRead (someSocket, data, propertySize);
return (void*) data;
}
It has to return a void pointer, as the data could be a struct (so one can just cast to the struct).
The problem is, I am using this pointer in my main program, and I want to delete it when I'm done. If I do this in my main program:
// inside main program
char* data = (char*) Library::getData(5);
// do stuff with data
delete[] data; // crashes with:
// *** glibc detected *** core: free(): invalid pointer: 0x00002aaab007bca4 ***
I thought maybe I should delete it in the shared library instead:
// inside library
void disposeData(void* data) { // call this from main program
delete[] (UINT8*) data; // cast it back to the original type of pointer
}
But I still get the same crash! Everything works fine and dandy if I don't delete, but I don't want unnecessary memory leaks all over my program.
I'm probably doing something dumb somewhere- please help me find the error in my ways!
EDIT: As pointed out in the comments, it seems that the above code works- I will have to see what specifically causes the errors in my code.
Have you tried using valgrind? Using valgrind will help you pinpoint a wide range of memory management errors, which are the likely cause of the problem. The error you are seeing looks either like heap corruption (as #nos says, probably in the do stuff part), or that you are not in fact freeing the same object you originally allocated.
If the library is providing you with allocated pointers, it should explain how to deallocate them. It may provide its own function for deallocation. Unless you have the source code to the library and can verify that it is using new[] to create the pointer, you can't be sure how it is allocating memory. Your crash is likely because your deallocator doesn't match its allocator.
How about using a more RAII based design such as smart pointers instead? Boost smart pointers are quite well designed.
I bet you're doing something like that, as you mention "casts":
#include <stdio.h>
class B { int x; };
class C { int y; };
class A : public B, public C { };
void* getData()
{
A* a = new A();
printf("%p\n", a);
C* c = a;
printf("%p\n", c);
return c;
}
void deleteData(void* x)
{
// delete (A*)x; // incorrect; causes crash
delete (A*)(C*)x; // correct
}
int main()
{
void* x = getData();
deleteData(x);
return 0;
}
Beware, the compiler may be translating what looks like an innocent cast into pointer arithmetic behind your back.