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);
Related
I have a class with a member function mBoundingBox made up of the following struct
typedef struct
{
unsigned int xMin;
unsigned int yMin;
unsigned int xMax;
unsigned int yMax;
} boundingBox;
class CImgProc
{
public:
CImgProc(void);
virtual ~CImgProc(void);
...
boundingBox *mBoundingBox;
...
}
In code I allocate the member:
mBoundingBox = new boundingBox [mBlobCnt];
piddle around with it (don't assign any pointers to it, just using array indexing), then, when I exit I:
if (mBoundingBox != NULL) delete [] mBoundingBox;
and this is causing an error.
Any input?
Updated info. The error does occur at termination in the destructor. The message generated by VS is:
Windows has triggered a breakpoint in ProcImage.exe.
This may be due to a corruption of the heap, ...
This may also be due to the user pressing F12 while ProcImage.exe has focus.
The output window may have more diagnostic information.
I am setting the pointer to NULL in the constructor and then allocating (with new) when I need to. The pointer is valid, but apparently not on the heap (break lands in dbgheap.c).
Once I allocate the memory, I don't happen to do any pointer magic with it. In this case I am looping through an image and gather stats. Then I use the stats stored in this memory to draw back into my image, but, again, in a rather brute force manner, so nothing else makes use of this memory.
It is legal for me to use new to create an array of structs isn't it?
Doh!!! Sorry to waste ya'lls time. I dug back in and discovered that my creation and destruction are fine, but somewhere in the middle I set the value of mBoundingBox[X]. whatever where it turns out X is the dim of the array created.
Typical user error, just a surprising place for the bug to show up.
Most probably you are deleting your array twice. To manage it better use
delete[] mBoundingBox;
mBoundingBox = 0;
instead of
if (mBoundingBox != NULL) delete [] mBoundingBox;
or even better use a smart pointer.
first of all the following check is wrong
if (mBoundingBox != NULL) delete [] mBoundingBox;
new does not returns NULL when it fails to allocate memory, rather it throws an exception.
use nothrow version of "new" if you want to proceed like you are doing. In nothrow version new will return NULL instead of throwing an exception.
mBoundingBox = new (std::nothrow) boundingBox [mBlobCnt];
Tutorials, searches, and the dim memory of my C++ formal education have left me clueless as to where I should use delete when I'm using a dynamically allocated object pointer in a loop, such as:
// necessary files are included, this code is within main
T * t;
t = foo.getNewT();
while (!t->isFinalT()) {
// print t stuff
delete t; // is this where I should delete t?
t = foo.getNewT();
}
delete t;
This lack of knowledge has become particularly troublesome on a recent class project. On my laptop (Linux Mint, g++ Ubuntu/Linaro 4.7.3-1ubuntu1) the code ran fine without the delete statement and crashed when I added the delete statement. On the school server (Solaris, g++ (GCC) 3.4.5), the code segfaulted after a few iterations without the delete statement, and runs fine when I add the delete statement.
How do I handle this kind of loop properly so that it will run in most environments?
Additional Info:
The error on my laptop occurs when the program reaches the delete request:
*** Error in 'program': free(): invalid next size (fast):...
Some of the other code:
// T.h
class T {
int id;
int num;
int strVarPos;
char * strVar;
public:
T();
~T();
// + misc. methods
}
// T.cpp
T::T() {
id = 0;
num = -1;
strVarPos = 0;
char * strVar = new char[11];
strVar[0] = '\0'
}
T::~T() {
delete [] strVar;
}
// Foo.cpp
T * Foo::getNewT() {
T * t = new T;
// populate T's fields
return t;
}
Resolution:
Because a simple test with just T * t and the loop worked ok, I ended up reconstructing the project starting from blank and adding one class at a time, to see when the problem would appear. Turns out that I had added additional content into a dynamically allocated array elsewhere in the program without updating the size constant I was using to initialize the array.
Evidently the school server could only handle the resulting memory discrepancy without crashing if I was making sure to delete the pointers properly (the program didn't run long enough to cause a significant memory leak in my tests), while my laptop wouldn't notice the memory discrepancy until I attempted to call delete (and then would crash).
Assuming that foo.getNewT() is handing ownership of the memory over to the caller:
T * t;
t = foo.getNewT();
//while (!t->isFinalT()) // if foo.getNewT ever returns NULL, this will be UB!!!
while (t != nullptr && !t->isFinalT())
{
// ...
delete t; // if you now own it and are no longer going to use it, yes, delete it here
t = foo.getNewT();
}
delete t; // you also need this one to delete the "final" t
However, you can avoid having to do it yourself by using std::unique_ptr:
std::unique_ptr<T> t;
t.reset(foo.getNewT());
while (t && !t->isFinalT())
{
// ...
t.reset(foo.getNewT());
}
Alternatively, you could rewrite the loop to flow a bit better:
std::unique_ptr<T> t;
do
{
t.reset(foo.getNewT());
if (t)
{
// do stuff with t
}
} while (t && !t->isFinalT());
the code ran fine without the delete statement and crashed when I
added the delete statement.
Are you sure getNewT is handing ownership of the T* to you? If you delete it, and then it tries to delete it later, you will end up with a heap corruption. If it is handing ownership over to the caller, and you do not delete it, you get a memory leak.
With the additional information in your edit:
char * strVar = new char[11];
That line is unnecessary if you declare strVar as either a std::string or a char[11]. If you attempt to copy any of those T objects, you'll be using the default copy constructor (as you have not defined one), which will do a shallow copy (that is, copy the value of the pointer for strVar). When you delete 2 Ts that are both pointing to the same memory location, you get a heap corruption. The most robust solution would be to declare strVar as a std::string.
The problem is not the delete. You have put it in the right place. It's more likely something else you are doing that is causing undefined behaviour.
Note that you should have a delete t after the loop as well (to catch the last one). This is assuming that foo.getNewT() always returns a valid pointer (which it must, because you never check if it is NULL).
You should delete a dynamically allocated memory when you no longer need it. If you want t to hold its value inside the for loop, then delete it outside the loop otherwise delete it inside.
However, the best thing to do is to use std::unique_ptr when you really have to use pointers . It will take care of deallocating the memory itself when all references to the memory are destroyed. You should try to avoid allocating memory as much as you can. Use STL containers if they fit the job.
I think when you delete t you are deleting the real object inside your structure.
Maybe that what is causing the problem.
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.
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).
I am trying a simple code in C++ but I am getting Debug Assertion Failed _BLOCK_TYPE_IS_VALID error when I delete the pointer. I don't know what I am making wrong. here is my code.
hash_map<string,string> m_hashDetails;
m_hashDetails.insert(hash_map<string,string>::value_type("test",*(new string("test123"))));
hash_map<string,string>::iterator myIterator;
myIterator = m_hashDetails.find("test");
if(myIterator == m_hashDetails.end())
{
printf("not found");
}
else
{
printf(myIterator->second.c_str());
//this is where I get Debug Assertion Failed _BLOCK_TYPE_IS_VALID
delete &(myIterator->second);
}
When i delete the second field of hash_map I get Debug Assertion Failed _BLOCK_TYPE_IS_VALID error. What I am making wrong? I have allocated the second field using new operator? One thing I have noticed that if I change the hash_map definition to
hash_map<string,string *> m_hashDetails; and insert values like
m_hashDetails.insert(hash_map<string,string>::value_type("test",new string("test123")));
then delete doesn't give the error.. and works fine? What is actual reason of this error?
You have allocated using operator new; BUT you are not storing the pointer to it. Rather you are storing of the allocated chunk;
int *p = new int(1); // ok, can be deleted later
int i = *new int(1); // memory leaked already, cannot delete as pointer is missed
Also, std::string is not a pointer type, so you cannot delete it.
So in your case, change the following line,
*(new string("test123"))
to
string("test123")
Then you don't have to delete it, as std::string is released automatically on the object destruction.