I am trying to delete memory allocation using a function.. The code is as follow...
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
int NOS, *NO, *SQR;
int Square()
{
SQR = new int [NOS];
if (!SQR)
{
cout<<"Mem Error SQR \n";
exit(0);
}
for ( int i = 0; i < NOS; i++ )
{
SQR[i] = NO[i]*NO[i];
}
}
void ERASE_MEM()
{
if (SQR) delete [] SQR;
cout<<"Deleted 1\n";
if (NO != NULL) delete [] NO;
cout<<"Deleted 2\n";
}
int main ()
{
cout<<"Enter No : ";
cin >> NOS;
NO = new int [NOS];
if (!NO)
{
cout<<"Mem Error NO \n";
exit(0);
}
for ( int i = 0; i < NOS; i++ )
{
NO[i] = 1+i;
}
Square();
delete NO;
ERASE_MEM();
}
If the number is less than 15, the program works fine but if the NOS is greater than 15, I get the following error:
* glibc detected ./MEM: double free or corruption (top): 0x097fa008 **
I am doing this in order to create one function for all the memory de-allocations, that I can call while allocating memory. If allocation fails, this function will de-allocate all previous allocations.
Thanks
You are deleting NO twice, once in main and once inside ERASE_MEM. Also, the syntax of delete used in main is wrong, since its an array you should use delete[] (or better remove the statement). BTW, one more thing to note is that when new fails it doesn't return a NULL pointer instead it throws std::bad_alloc exception. So there is no point validating the memory location retunred from new. Also, do not use all capital letters for a function name, the general coding practice is to use the all caps name for macros only. It is also not necessary to check for NULL pointer before calling delete[]. Standard guarantees that deleting a NULL pointer will not do anything.
You delete NO (incorrectly) in the main code and then again (correctly) in ERASE_MEM
edit: calling delete doesn't set pointer to null, it can't do this since the call only gets the value of the pointer, not the pointer itself.
This is a little clearer with the 'C' version free(pData) can't change pData - only what pData points to. A common 'C' idiom is to define your own Free(void **ptr) which you call with Free(&pData) which can then set pData to NULL.
Also note that it's perfectly safe to call free / delete with a null pointer, the function does the check for you.
Don't feel too bad delete and delete [] are a nasty corner of C++, they are function calls that look like statements, and the [] syntax to delete and array is even worse. The only good part is that with smart pointers and modern C++ you never have to use them
Related
I've been having trouble understanding the delete and delete [] functions in C++. Here's what I know so far:
aClass *ptr = new aClass(); //Allocates memory on the heap for a aClass object
//Adds a pointer to that object
...
delete ptr; //ptr is still a pointer, but the object that it
//was pointing to is now destroyed. ptr is
//pointing to memory garbage at this point
ptr = anotehrOjbectPtr //ptr is now pointing to something else
In the case that this happens,
aClass *ptr new aClass();
...
ptr = anotherObjectPtr
the object that pointer was pointing to, is now lost in memory, adn this will cause a memory leak. The object should've been deleted first.
I hope the above is correct
But I wrote this small program, where I'm getting some unexpected behaviour
#include <iostream>
#include <string>
using namespace std;
class Database {
private:
Database() {
arrNames = NULL;
capacity = 1;
size = 0;
}
Database(const Database &db) {}
Database &operator=(const Database &db) {}
string *arrNames;
int capacity, size;
public:
static Database &getDB() {
static Database database;
return database;
}
void addName(string name) {
if (arrNames == NULL) {
arrNames = new string[capacity];
}
if (size == capacity - 1) {
capacity *= 2;
string *temp = new string[capacity];
int i = 0;
while (i <= size) {
temp[i] = arrNames[i];
i++;
}
delete [] arrNames;
arrNames = temp;
}
arrNames[size] = name;
size++;
}
void print() {
int i = 0;
while (i <= size) {
cout << arrNames[i] << endl;
i++;
}
}
};
int main() {
Database &database = Database::getDB();
Database &db = Database::getDB();
Database &info = Database::getDB();
database.addName("Neo");
db.addName("Morpheus");
info.addName("Agent Smith");
database.print();
db.print();
info.print();
}
In the addName function, when I call delete [] arrNames, what I think is happening is that the memory associated with the current array arrNames is destroyed, so arrNames is now pointing at garbage, Then arrNames is directed to point to another location in memory that is pointed to by temp. So if I hadn't called delete [] arrNames, then that location in memory would've been invalid, causing a memory leak. However, when I comment out that line, the code still works without problems. Am I not understanding something here?
Sorry that this si so long
Thanks for the halp
However, when I comment out that line, the code still works without problems. Am I not understanding something here?
An important thing to know about programming is that doing things correctly is not merely a matter of having things apparently work.
Often times you can try something out hand have things appear to work, but then some outside circumstances change, something you're not explicitly controlling or accounting for, and things stop working. For example you might write a program and it runs find on your computer, then you try to demo it to someone and happen to run it on their computer, and the program crashes. This idea is the basis of the running joke among programmers: "It works for me."
So things might appear to work, but in order to know that things will work even when conditions change you have to meet a higher standard.
You've been told how to do things correctly with delete, but that doesn't necessarily mean that things will break in an obvious way if you fail to do so. You need to abandon the idea that you can definitively determine whether something is correct or not by trying it out.
From what I think I see in your code, it looks like addName() is meant to append the new name onto the dynamic array. Doing this yourself can be headache inducing, and there is an existing convenient STL template for just this which I strongly recommend, called vector, from the <vector> header.
If you add #include <vector> and change string *arrNames to vector<string> arrNames, then your entire addName() function can be reduced to:
void addName(string name){
arrNames.push_back(name);
}
From the vector.size() method, you can determine the current length of the vector as well, and your members capacity and size are no longer needed.
A memory leak doesn't involve anything being made invalid. Quite the reverse, it's a failure to make a memory location invalid, causing it to remain in use even when it shouldn't be.
First of all, when you delete something, you are not destroying it in memory, just making it available for some further allocation. This is somewhat similar to filesystem - when you delete file, you just say space it occupied is now available for some new data. You could actually retrieve unmodified data after you called delete on them, but this is undefined behavior and will be compiler/OS specific.
If you don´t delete[] arrNames, you leave its data forgotten in your process´s memory, and creating memory leak. But beside this fatal flaw, there is no more magic happening.
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.
int main()
{
cout<<"Enter n";
cin >> n;
int * a = new int[n];
a = foo(n);
free(a);
return -1;
}
int * foo(int n)
{
int * a = new int [n];
if(!a) // what should I return here if allocation of a fails
{}
free(a);
}
In the code above I am trying to catch the return value of an function from main, the return type of the function is a pointer . However I am allocating memory dynamically . So , what should I return if my memory allocation fails ... any special symbol like NULL .
P.S - Its a very basic question and could not formalize my question to any succinct form for to search over Google.
Edit: Thanks all of you guys . I have solved my problem .
It is a custom to return NULL in case of allocation failure from functions which allocate their own memory and return pointer to it. See for example strdup(). Note that operator new throws std::bad_alloc if it fails to allocate memory, so you may need to catch this if you want to return NULL or alternatively, you can let std::bad_alloc propagate out of the function.
Note however, that it is not always wise to return such pointers since it raises the issues of ownership and increases the likelihood of memory leaks.
You may find that sticking to the RAII idiom makes your code easier to reason about and less error prone. One consequence of RAII idiom is that allocation and deallocation are done by the same code unit.
In your particular situation you allocate the array in main() so you may pass the pointer to it to foo() and deallocate memory also in main().
Also, if you use new to allocate, you should use a proper version of delete to deallocate (here delete[] since you allocated an array). You use free() to deallocate memory allocated with malloc() and friends.
operator new throws exception (except nothrow operator new), so, you can catch this exception and return null pointer, or rethrow, or throw other exception.
The newoperator throws a bad_alloc exception if allocation fails. So you can catch this exception and handle the error.
For exemple:
#include <new> // std::bad_alloc
int* foo(int n)
{
int* a(new int[n]);
return a; // I guess you want to return the address stored in a
}
int main()
{
try
{
int* a(foo(n));
}
catch(std::bad_alloc& ba)
{
// Handle here the error (e.g: std::cerr << "Allocation failed:" << ba.what() << std::endl;)
}
return 0;
}
EDIT1: If you use C++11 features, forget NULL or 0 and use nullptr instead!
If your return value is a pointer then NULL is the most logical value in the case of an error. You could also look at raising an exception, but for now returning NULL should suit your needs.
The new operator would throw a bad_alloc exception in such a case and probably you should catch it and handle it according to your requirements (http://www.cplusplus.com/reference/std/new/bad_alloc/)
It can return any value. The thing is that then you have to treat it correctly.
if(!a) // what should I return here if allocation of a fails
{ return NULL;}
this will imply allocation failed i.e. by returning a NULL pointer.
I am trying a code which Goes like this:-
class test{
int test_int;
public:
virtual int show()
{
return test_int;
}
void set_int(int data){
std::cout<<"received data "<< data <<endl;
test_int = data;
}
};
int main()
{
test *ptr=new test();
ptr=NULL;
ptr->set_int(5);
return 0;
}
Now the problem i am facing is my program after printing the data which i am sending through set_int function got printed but the program crashes just after the completition of the function(set_int).
Am i doing any mistake that is not according to the language standards?
TIA.
Am i doing any mistake that is not according to the language standards?
Yes, you are.
You may not call member functions on a pointer that does not point to a valid object of that type. A null pointer never points to a valid object.
The trivial fix here is to remove the line ptr=NULL;. That way ptr still points to an object when the member function is invoked. This also allows you to fix the memory leak by deleting the pointer later. As a sidenote: avoid manual memory management.
You have pointer to test (test*) set to dynamicaly allocated memory representing instance of that class.
Right after that, you wrote "Nah, I do not need it anymore" and you forget where that newly allocated memory was.
Finally, you are trying to access an object on address 0, which is an invalid operation and will cause runtime error.
You probably meant to do this
int main()
{
test *ptr = new test();
ptr->set_int(5);
// ptr = NULL; // wont free the memory allocated by new
delete ptr; // memory deallocation
ptr = NULL; // now we can safely forget that address (which is now invalid anyways)
return 0;
}