Here is my function:
void Tetris::place_square(int* coords,char type){
if (coords[1]>heights[coords[0]]){
char* old=data[coords[0]];
data[coords[0]]=new char[coords[1]];
for (unsigned int i=0; i<heights[coords[0]]; ++i){
data[coords[0]][i]=old[i];
}
for (unsigned int i=heights[coords[0]]; i<coords[1]; ++i){
data[coords[0]][i]=" "[0];
}
data[coords[0]][coords[1]-1]=type;
heights[coords[0]]=coords[1];
delete old;
} else {
data[coords[0]][coords[1]-1]=type;
}
}
It compiles fine but when I try to run it i get malloc: *** error for object 0x7fff503e0020: pointer being freed was not allocated
I believe the problem is delete old; but I don't know how to fix it.
Looking at this section:
char* old=data[coords[0]];
data[coords[0]]=new char[coords[1]];
I'm not sure what is in your data array, but it looks like you are assigning a pointer which has not yet been initialized.
If you are initializing with
data[i]=new char[0];
Then you should also be deleting with delete[].
The address indicates that data[coords[0]] was previously pointing to an automatic variable. You can only use delete on things that were allocated by new.
Also, you should use delete[] when things were allocated by new[] as they are in this example.
To fix this you will need to review the initialization of data and any code that might update data[x] . It is also possible that coords[0] is out of bounds for data.
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);
If I have:
template<>
char *toBytes<uint64_t>(uint64_t src) {
char *data = new char[8];
//...stuff
return data;
}
template<>
void write<uint64_t>(char *dst, uint64_t src) {
char *srcBytes = toBytes(src);
for (int i = 0; i < 8; ++i) {
*(dst++) = *(srcBytes++); //am I leaking here?
}
}
that gets called with something like:
char *keyPtr = new char[27];
//...stuff
write(keyPtr, 1234ull);
//...write up to 27
If do delete[] keyPtr; would I have deleted srcBytes? I think the question is, on the line asking if I'm leaking, is that doing a copy and as a result deleting keyPtr leaves srcBytes still to be deleted?
Still learning C++ and it's not always clear to me when the copy constructor is called vs the assignment operator.
EDIT 1:
Fixed delete as per #Steephen's answer
EDIT 2
Add toBytes as per #WhozCraig's comment
You have to use
delete [] keyPtr;
instead of calling delete over for loop;
If you allocate memory using new[], you should use delete [], and if you use new, you should use delete. In your case you are using the former one.
I think the question is, on the line asking if I'm leaking, is that
doing a copy and as a result deleting keyPtr leaves srcBytes
If your program allocated memory for srcBytes using new operator you should delete it it as same way you do for keyPtr . Because resource handling by both pointers are independent even after your assignment in your case.
You have a memory leak. No, delete []-ing keyPtrhas nothing to do with srcBytes, an independent allocation. The two addressed buffers are unrelated (except for content due to your copy-code).
Apart from the obvious (using std::vector<> and letting RAII take over the memory management for all of this), a fairly minimal change to your code to plug the leak would loop something like this:
template<>
void write<uint64_t>(char *dst, uint64_t src)
{
char *srcBytes = toBytes(src);
std::copy(srcBytes, srcBytes+8, dst);
delete [] srcBytes;
}
or using a smart pointer:
template<>
void write<uint64_t>(char *dst, uint64_t src)
{
std::unique_ptr<char[]> srcBytes(toBytes(src));
std::copy(srcBytes.get(), srcBytes.get()+8, dst);
}
Both use the std::copy stock algorithm which both accomplishes what you seem to want, while retaining the original result of toBytes for proper cleanup. Which you choose (or perhaps something entirely different still) I leave to you.
Best of luck.
These are a few cases where you will leak the memory where you used "new":
The function runs out of scope before you could delete it and there is no pointer to the allocated memory outside of the function.
You forget to delete where appropriate
You mix delete and delete []
Exception is caught between the use of "new" and "delete".
Even as a beginner, it's a good idea to get familiar with smart pointers.
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've been brushing up on my C++ as of late, and I have a quick question regarding the deletion of new'd memory. As you can see below i have a simple class that holds a list of FileData *. I created an array to hold the FileData objects to be pushed into the list. When ReportData is destructed I loop through the list and delete each element. My question is, how can i delete the array when I'm done using reportData, so that I do not have any memory leaks?
Report.h
class REPORTAPI ReportData {
public:
ReportData()
{
}
virtual ~ReportData()
{
printf("Starting ReportData Delete\n");
for (list<FileData*>::iterator i = ReportFileData.begin(), e = ReportFileData.end(); i != e; )
{
list<FileData*>::iterator tmp(i++);
delete *tmp;
ReportFileData.erase(tmp);
}
for (list<SupressionData*>::iterator i = ReportSupressionData.begin(), e = ReportSupressionData.end(); i != e; )
{
list<SupressionData*>::iterator tmp(i++);
delete *tmp;
ReportSupressionData.erase(tmp);
}
ReportFileData.clear();
ReportSupressionData.clear();
printf("Finished ReportData Delete\n");
}
list<FileData *> ReportFileData;
list<SupressionData *> ReportSupressionData;
}
extern "C" __declspec(dllexport) FileData* __stdcall createFileData(string fileName, long recordCount, long addPageCount)
{
return new FileData(fileName, recordCount, addPageCount);
}
Main.cpp
ReportData *reportData = createrd();
if (reportData != NULL)
{
CreateFileDataFunc createfd (reinterpret_cast<CreateFileDataFunc>(GetProcAddress (dll, "createFileData")));
const int num_files = 5;
FileData *fileData[num_files];
char buff[256] = {'\0'};
for (int i = 0; i < num_files; i++)
{
sprintf(buff, "test: %d", i);
fileData[i] = createfd(buff, 1, 1);
reportData->ReportFileData.push_back(fileData[i]);
}
delete reportData;
reportData = NULL;
delete [] fileData; // this is throwing an access violation error:
//EAccessViolation: 'Access violation at address 326025AF. Write of address 00000008'.
}
--- I removed the delete oprations from the ReportData dtor
and I'm now looping and deleting:
for(int i = 0; i < num_files; i++)
{
delete fileData[i];
}
This is easier to understand then having to rely on a separate object's dtor to clean up memory.
You don't. fileData is an automatic (stack) variable. You didn't allocate it with new, so you don't delete it.
[Edit: also I'm not sure, but I think you could face problems deleting those FileData objects from main.cpp, considering that they were allocated in some dll. Does the dll provide a deleter function?]
Your array is not dynamically allocated, so you don't need to delete it. Each element, however, is pointing to a dynamically allocated object (from your comment):
createfd is a function pointer that returns a new instance of FileData though
What you need to do is loop over the elements of the array, and free each of them.
for(int i = 0; i < num_files; i++)
{
delete fileData[i];
}
// allocate on the stack, no manual delete required
FileData *fileData[num_files];
// allocate on the heap, must delete after usage
FileData *fileData = new FileData[num_files];
// ..
delete [] fileData;
Have you thought about wrapping FileData* with a smart pointer?
The problem with your dtor is that an exception will cause a memory leak (with some other problems relating to exceptions leaking out of dtor's).
"My question is, how can i delete the array when I'm done using reportData, so that I do not have any memory leaks?"
That's the wrong question. The right question is "who should delete these FileData objects?", and the answer is "whoever constructs them, ideally, in this cae Main.cpp". Farming out the job to reportData is awkward and precarious; doing the job twice (once in the ReportData destructor and again in Main.cpp) violates memory.
If you must destroy the objects in ~ReportData(), just don't do anything about them in Main.cpp. Then your code will be correct. Horrible, but correct.
Don't deallocate anything in main().
The destructor for reportData will handle everything allocated with createfd() (just make sure that createfd() is returning what it allocated with new(), since you must not delete anything that was not new'd).
fileData is allocated locally, on the stack, not through new. Since it wasn't allocated by new, don't delete it.
The pointers that were passed into fileData were also passed into reportData, and reportData is responsible for all deletions there. You could check to see that they weren't allocated from an inaccessible memory pool (say in a dynamically linked library); if they were, that's a problem.
So, assuming the deletes are correct in the ReportData destructor, remove any deletion of fileData and you're good.
There is no need to delete or clear either of the two lists - this will be done for you by the default destructor. Assuming that the pointers the lists contain (to "arrays"? I'm not clear) have been dynamically allocated, you need to delete them. However, you can (and should) avoid having to do this explicitly by making the lists contain std::vectors or suitable smart pointers.