How to delete a pointer after returning its value inside a function
Solution 1
Dynamic arrays are freed using delete[]
:
char* block = ReadBlock(...);
// ... do stuff
delete[] block;
Ideally however you don't use manual memory management here:
std::vector<char> ReadBlock(std::fstream& stream, int size) {
std::vector<char> memblock(size);
stream.read(&memblock[0], size);
return memblock;
}
Solution 2
Just delete[]
the return value from this function when you've finished with it. It doesn't matter that you're deleting it from outside. Just don't delete it before you finish using it.
Solution 3
You can call:
char * block = ReadBlock(stream, size);
delete [] block;
But... that's a lot of heap allocation for no gain. Consider taking this approach
char *block = new char[size];
while (...) {
stream.read(block, size);
}
delete [] block;
*Note, if size
can be a compile time constant, you can just stack allocate block
.
Solution 4
I had a similar question, and produced a simple program to demonstrate why calling delete [] outside a function will still deallocate the memory that was allocated within the function:
#include <iostream>
#include <vector>
using namespace std;
int *allocatememory()
{
int *temppointer = new int[4]{0, 1, 2, 3};
cout << "The location of the pointer temppointer is " << &temppointer << ". Locations pointed to by temppointer:\n";
for (int x = 0; x < 4; x++)
cout << &temppointer[x] << " holds the value " << temppointer[x] << ".\n";
return temppointer;
}
int main()
{
int *mainpointer = allocatememory();
cout << "The location of the pointer mainpointer is " << &mainpointer << ". Locations pointed to by mainpointer:\n";
for (int x = 0; x < 4; x++)
cout << &mainpointer[x] << " holds the value " << mainpointer[x] << ".\n";
delete[] mainpointer;
}
Here was the resulting readout from this program on my terminal:
The location of the pointer temppointer is 0x61fdd0. Locations pointed to by temppointer:
0xfb1f20 holds the value 0.
0xfb1f24 holds the value 1.
0xfb1f28 holds the value 2.
0xfb1f2c holds the value 3.
The location of the pointer mainpointer is 0x61fe10. Locations pointed to by mainpointer:
0xfb1f20 holds the value 0.
0xfb1f24 holds the value 1.
0xfb1f28 holds the value 2.
0xfb1f2c holds the value 3.
This readout demonstrates that although temppointer (created within the allocatememory function) and mainpointer have different values, they point to memory at the same location. This demonstrates why calling delete[] for mainpointer will also deallocate the memory that temppointer had pointed to, as that memory is in the same location.
Solution 5
Yes. You may call delete from outside of the function. In this case though, may I suggest using an std::string so you don't have to worry about the management yourself?
Emer
Updated on June 14, 2020Comments
-
Emer almost 4 years
I have this function:
char* ReadBlock(fstream& stream, int size) { char* memblock; memblock = new char[size]; stream.read(memblock, size); return(memblock); }
The function is called every time I have to read bytes from a file. I think it allocates new memory every time I use it but how can I free the memory once I have processed the data inside the array? Can I do it from outside the function? Processing data by allocating big blocks gives better performance than allocating and deleting small blocks of data?
Thank you very much for your help!
-
Clark Gaebel almost 14 yearsVariable sized arrays aren't ISO C++, it's a GCC extension.
-
Clark Gaebel almost 14 yearsThe definition of the function says that: char* ReadBlock(..., int size);
-
Stephen almost 14 years@wowus : This would obviate the need for the function, anyways, point taken... commented.
-
Georg Fritzsche almost 14 yearsIt has to be
delete[]
, notdelete
. -
Emer almost 14 yearsOk, but I cannot use strings because of read. istream& read ( char* s, streamsize n );
-
TOMKA almost 14 yearsWith this method, when the vector object is returned, does its copy constructor get called (I mean, do two instances exist at one point)?
-
Georg Fritzsche almost 14 years@dream: It depends, most likely named return value optimization, NRVO, will kick in. See also the interesting Want Speed? Pass by value..
-
Emer almost 14 yearsWouldn't I run out of memory if I don't delete already read memory blocks?
-
Clark Gaebel almost 14 yearsThen use a vector instead. Sorry, didn't notice that.
-
Georg Fritzsche almost 14 yearsStephen, why has this become
new int[size]
instead ofnew char[size]
? -
Stephen almost 14 years@emerrf : You can reuse the same buffer, if your application allows for it (whether that's true isn't clear from your question). If it 's not possible to reuse the same buffer, then you should use a different approach - such as returning a string.
-
Stephen almost 14 years@Georg : Interesting post, but very misleading name. It almost sounds as if they're arguing pass-by-value instead of pass-by-reference. Link bait, I guess.
-
sigfpe almost 14 yearsOuch! The sad thing is that if you make this mistake, the compiler can't even detect it. What an awful language. Anyway, thanks. I'll fix the post. (Though it must be said, I wasn't actually proposing the entire line of code, just what builtin to use.)
-
0xdky almost 14 yearsIf it is not as trivial as the above example, I would always use BOOST shared_ptr (or intrusive_ptr if the type of data is a class). It may sound heavy weight but leads to consistent leak free code (almost).
-
Georg Fritzsche almost 14 years@hack: Then
shared_array<T>
would be a better fit here, no need for a custom deleter. -
TOMKA almost 14 years@Georg: Ah I see! So, if I read correctly, the standard permits an optimisation that prevents a copy constructor from being called even if the copy ctor has side effects?
-
Georg Fritzsche almost 14 years@dream: Yep, its a notable exception to the rule of not changing the observable behaviour. RVO is e.g. observable with logging-statements in both ctor and copy-ctor with
X f() { return X(); } X x = f();
(activated optimizations assumed). If you have a standard handy see §12.8/15.