Should i use delete[] in a function? [duplicate] - c++

This question already has answers here:
Is not calling delete on a dynamically allocated object always a memory leak?
(6 answers)
Closed 6 years ago.
void work() {
int *p;
p=new int[10];
//some code....
}
I have a short question that in the work function, should i use delete[] operator? since when work function is over, p will be destroyed, which is wrong or right ? (My English is bad, i am sorry).

This will work as long as the code throws no exceptions...
void work() {
int *p;
p=new int[10];
//some code....
delete [] p;
}
This is better (but difficult to maintain):
void work1() {
int *p;
p=new int[10];
try {
//some code....
} catch(...) {
delete [] p;
}
delete [] p;
}
This is much better...
void work2()
{
auto p = std::unique_ptr<int[]>(new int[10]);
// some code...
// memory is automatically deleted
}
And this is how you should do it...
void work3()
{
auto v = std::vector<int>(10);
// some code...
}

You're right, if you have no reference to p outside of the function, e.g. a global variable, then you need to call delete [] p right inside of the function, otherwise the reference to the allocated memory you want to free is lost.

Yes, if integers are allocated using new int[10], you need to clean up using delete[], since it is an array.

Yes, you need to release the memory from new.
Alternatively with C++11, you can use smart pointer:
void work() {
std::unique_ptr<int[]> p{ new int[10] };
//some code....
// RAII will delete[] magically here
}
Alternatively, if you are using just few integers (10 in your case), that are known in compile time, you can do "normal" or static array. e.g.
void work() {
/* static */ int p[10];
//some code....
}
Alternatively, use std::vector:
void work() {
std::vector<int> p{10};
//some code....
// RAII will delete[] magically here
}
Alternatively, with C++11 if array size is known in compile time, use std::array:
void work() {
std::array<int,10> p;
//some code....
// RAII will delete[] magically here
}

Related

return pointer with new operator. Where to put delete?

Im fairly new to C++.
So I learned that new allocates memory and returns a pointer of my datatype. But can I use this in a function and return the pointer? If so then where should I place the delete operator?
Is the following code legal?
int *makeArray(int size)
{
int *result = new int[size];
delete[] result;
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... */
return 0;
}
It is compiling and working but logically it makes no sense because I deleted my array.
So I tried the following:
int *makeArray(int size)
{
int *result = new int[size];
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... do some stuff with pointer */
delete[] pointer;
return 0;
}
Is this safe or does it cause a memory leak? Is there a better way of returning the pointer?
I tried both versions and they are compiling and working but I'm sure at least one of them if not both are unsafe.
Is the following code legal?
int *makeArray(int size)
{
int *result = new int[size];
delete[] result;
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... */
return 0;
}
Definitely not! This is Undefined behavior because you return a deleted pointer. After using the delete operator you're telling your OS that it can release the memory and use it for whatever it wants. Reading or writing to it is very dangerous (Program crashing, Bluescreen, Destruction of the milky way)
int *makeArray(int size)
{
int *result = new int[size];
return result;
}
int main()
{
int *pointer = makeArray(10);
/* code ... do some stuff with pointer */
delete[] pointer;
return 0;
}
Is this safe or does it cause a memory leak?
Yes this is the correct way of using the new and delete operator. You use new so your data stays in memory even if it gets out of scope. Anyway it's not the safest code because for every new there has to be a delete or delete[] you can not mix them.
Is there a better way of returning the pointer?
YES. It's called Smart Pointer. In C++ programmers shouldn't use new but smart pointer at all. There is a C++ community Coding Guideline to avoid these calls Guideline R11

Memory leak in this situation? Using new keyword over and over

I'm very cautious about memory leaks, so I thought I'd have this verified. In the following example would there be a memory leak? My gut instinct says yes.
class Handler // Class definition
{public:
~Handler();
int* ptrToInts;
};
Handler::~Handler() // Class destructor
{
delete[] ptrToInts;
}
Handler handler; // Global object
void aFunction()
{
handler.ptrToInts = new int[20];
}
int main()
{
bool quit = false;
while(!quit)
{
aFunction();
}
return 0;
}
Would ptrToInts be creating 20 separate new ints in separate memory on the heapeach time?
Also, another question is if it weren't for the destructor, would the dynamically allocated memory be freed? Seeing as though the lifetime of the class is the duration of the program, would it do cleanup of all the "new" memory?
Edit: Thanks for the answers. The reason I'm asking this is because I'm trying to get around calling new and delete every time WndProc is called for Raw Input basically, which is how the MSDN tells you to do it. Seems very inefficient.
As soon as you re-assign your pointer without using delete[] to de-allocate that allocated memory on the heap, you create a memory leak. This will happen if you loop your aFunction() as it re-assigns the pointer every time it is called.
As for your second question, your destructor will only delete[] the last array assigned to the pointer.
Only delete[] frees the memory that was allocated by new. And every time you use new, you need a delete.
For the other question, based on the Documentation:
MyClass * p1 = new MyClass[5]; // allocates and constructs five objects
Yes, there is a memory leak when you call the function more than once, without explicitly deallocating handler.ptrToInts after each call;
void aFunction()
{
handler.ptrToInts = new int[20];
}
//-----somewhere we see the caller
while(!quit)
{
aFunction();
}
However, this is a trivial case of detecting leaks... You should learn to use Leak detectors and static analyzers.
See How do you detect/avoid Memory leaks in your (Unmanaged) code?
Of course there is a memory leak. You allocate the ints in
void aFunction()
{
handler.ptrToInts = new int[20];
}
without deallocating the old ints first, like
void aFunction()
{
delete [] handler.ptrToInts;
handler.ptrToInts = new int[20];
}
would do.
Calling aFunction() will lead to "infinite" memory allocations.
And your destructor, which only frees the last allocated ints, even is never called.
Why is your handler not managing it's own memory?
It's very bad practice to allocate memory outside of your object and free it inside or vice versa.
Why not implement the Handler class this way:
class Handler
{
public:
Handler();
~Handler();
void aMethod();
private:
int* ptrToInts;
};
Handler::Handler() {
handler.ptrToInts = new int[20];
}
Handler::~Handler() {
delete[] ptrToInts;
}
void Handler::aMethod() {
delete[] ptrToInts;
handler.ptrToInts = new int[20];
}
int main() {
bool quit = false;
Handler handler;
while(!quit) {
handler.aMethod();
}
}

Best strategy for manual memory management using smart pointers?

Is there a recommended strategy for dealing with external libraries which expect manually managed raw pointers. For example a method which takes a vector of pointers:
ALibraryFunc(std::vector<ALibraryData*> p);
so generally you'd create your vector with something like:
std::vector<ALibraryData*> myVec;
for(...)
{
myVec.push_back(new ALibraryData(args));
}
//and then
ret = ALibraryFunc(myVec);
//and then
for(auto &a:myVec)
{
delete a;
}
myVec.clear();
I'd much prefer to use smart pointers but the library will not take them. This leaves me wondering if something like this is more stinky than just doing it manually:
std::vector<std::unique_ptr<ALibraryData>> myVecUP;
std::vector<ALibraryData*> myVec;
for(...)
{
myVecUP.push_back(std::make_unique<ALibraryData>(args));
myVec.push_back(myVecUP.back().get());
}
//and then
ret = ALibraryFunc(myVec);
myVec.clear();
myVecUP.clear();
The second version seems safer in case of exceptions or mistakes but it does risk dangling pointers. Am i missing something obvious here? What do/would you do?
You can declare a small class which will own the vector of raw pointers, and delete the pointers in the destructor:
struct VecOwner {
std::vector<ALibraryData*> vec;
VecOwner(<some arguments>)
{
// fill the vector here
}
~VecOwner()
{
for(auto &a:vec)
delete a;
vec.clear();
}
};
you should be able to reuse the class in all places where you use the library.
You can use 'scope exit' idiom :
//open scope block
{
std::vector<ALibraryData*> myVec;
////////////////////////////////////////
struct MyVecRAIICleaner{
std::vector<ALibraryData*> * myVecPtr;
~MyVecRAIICleaner(){
if (myVecPtr) {
for(auto& a: *myVecPtr)
delete a;
myVecPtr->clear();
}
}
} myRAIICleaner = {&myVec};
////////////////////////////////////////
for(...)
{
myVec.push_back(new ALibraryData(args));
}
//and then
ret = ALibraryFunc(myVec);
/** You needn't below code. */
////and then
//for(auto &a:myVec)
//{
// delete a;
//}
//myVec.clear();
}// end scope block
EDIT:
I'm sorry, but Wojtek Surowka's answer is not exception safe or required extra try catch block in constructor.

loop for with class functions error when condition too high

Last time I'm constantly getting an error with for-loop.
The easiest way to show it is:
#include <iostream>
class Class
{
private:
int number;
public:
Class(int a);
void get();
};
Class::Class(int a)
{
number=a;
}
void Class::get()
{
std::cout<<number<<std::endl;
}
int main()
{
int amount=4;
Class* p[amount];
for(int i=0;i<amount;i++)
{
delete p[i];
p[i]=new Class(i);
}
for(int i=0;i<amount;i++)
{
p[i]->get();
}
return 0;
}
Program is returning 255, and while debugging I'm getting a SIGSEGV signal - segmentation fault.
I found one thing very strange: when amount=3 or less program works properly. I'm going to use it for over 700 elements, so I've found this quite disappointing.
I'm using Windows 7 and Code::Blocks 13.12 with GNU GCC Compiler.
What should I change in this program so that it works properly? I'm pretty sure that's only my small knowledge about c++ or something like that.
Thanks in advance.
Class* p[amount];
for(int i=0;i<amount;i++)
{
delete p[i];
p[i]=new Class(i);
}
You should remove the line delete p[i]; since the array p is not initialized yet.
You are consistently calling delete on pointers that don't point to dynamically allocated objects:
Class* p[amount]; // array of uninitialized pointers
delete p[i]; // oops
Here is what's going on (see comments):
// This allocates `amount` spots for pointers
Class* p[amount];
// Your pointers are not initialized yet
for(int i=0;i<amount;i++)
{
// You are trying to delete what they point to
delete p[i]; // <<== This is undefined behavior
p[i]=new Class(i);
}
You should not call delete until after you have allocated the objects being deleted. Otherwise, it's undefined behavior, i.e. your program may crash.
Finally, you need to delete the pointers after you are done with them to avoid memory leak. You could use a vector of smart pointers for that (recommended), or simply add another loop to your program, like this:
int amount=4;
Class* p[amount];
for(int i=0;i<amount;i++)
{
p[i]=new Class(i);
}
for(int i=0;i<amount;i++)
{
p[i]->get();
}
for(int i=0;i<amount;i++)
{
delete p[i];
}
initialize p[i] along with declaration.
Class* p[3] = {0}; delete has built in null check, with that you will not get any error
you should be getting error even when amount is 3 or less than three

Dynamic memory deletion within functions

this is my first post, so sorry if it is not asked well.
Basically I am having trouble with dynamic memory and i would like to know if it is me misunderstanding the concept, or at least one of the functions. Ok, so i'm using C++ where I need to manage an array that changes size within the main program loop but i keep getting a heap error when i try to delete the memory. (below is a simplified version of what i'm trying to do).
void main(void)
{
//Initialization
//main loop
while(true)
{
int* array;
function(&array);
printf("test %d",array[0]); //basically use the data
delete [] array;
}
}
//in separate file
void function(**int val)
{
*val=new int[size of array] // i pass the size of the array...
//to the function as well
//fill the array with data
return;
}
Ok so after this i can read the data so it must be attached to the pointer "array" but then why would it not allow me to delete the data as if it was already deleted?
Any advice would be much appreciated thanx.
Not the main problem but you actually have the syntax wrong here,
void function(**int val);
It should be:
void function(int **val);
But you don't need a double pointer as you can simply pass the pointer by-reference:
void function(int *&val);
It follows that your program should be like this:
int main() // main should return int
{
int *array;
function(array, 5);
printf("test %d", array[0]);
delete [] array;
}
void function(int *&val, int size)
{
val = new int[size];
}
You also didn't need the while (true) loop either.
You said that "any advice" was welcomed, so here's my advice:
Don't use C-style arrays in the first place, and this won't be a problem. Use a vector instead:
#include <vector>
#include <algorithm>
void main(void)
{
//Initialization
//main loop
while(true)
{
std::vector <int> array;
function (array);
printf ("test %d", array[0]);
}
}
//in separate file
void function(std::vector <int>& vec)
{
vec.push_back (1);
vec.push_back (2);
// ...etc...
}
Above is a basic and naive implementation that uses a vector instead of C-style arrays and dynamic memory management. There are many opportunities for improvement, but you get the idea.
Your code, in its current state, should work. However, it is very bad practice to use new and delete like that, especially with new/delete in different places.
You should use std::vector instead:
// main function
std::vector<int> array = function();
printf("test %d",array[0]); //basically use the data
And your function() would be:
std::vector<int> function()
{
std::vector<int> val(size);
//fill the array with data
return val;
}
Another idea. The value in passing things by reference is the copying cost of large objects. With pointers you don't need to worry about this. This code could be cleaned up like this as well.
int main() // main should return int
{
int *array = function(SOME_SIZE);
printf("test %d", array[0]);
delete [] array;
}
int * function(int size) //Just return the pointer
{
int *temp = new int[size];
return temp;
}
Since we're dealing with pointers... returning them isn't a big deal, and is typical practice when you need to "transfer" ownership of a dynamically allocated object. That being said, the post that references using vectors or other standard containers is the best approach. Avoiding use of new and delete makes code much safer.