简体   繁体   中英

How to delete a pointer after returning its value inside a function

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!

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;
}

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.

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 .

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?

first thing to note: memory allocated with new and delete is completely global. things are not automatically deleted when pointers go out of scope or a function is exited. as long as you have a pointer to the allocation (such as the pointer being returned there) you can delete it when ever and where ever you want. the trick, is just makeing sure other stuff doesn't delete it with out you knowing.

that is a benefit with the sort of function structure the fstream read function has. it is fairly clear that all that function is going to do is read 'size' number of bytes into the buffer you provide, it doesn't matter whether that buffer has been allocated using new, whether its a static or global buffer, or even a local buffer, or even just a pointer to a local struct. and it is also fairly clear that the function is going to do nothing more with the buffer you pass it once it's read the data to it.

on the other hand, take the structure of your ReadBlock function; if you didn't have the code for that it would be tricky to figure out exactly what it was returning. is it returning a pointer to new'd memory? if so is it expecting you to delete it? will it delete it it's self? if so, when? is it even a new pointer? is it just returning an address to some shared static buffer? if so, when will the buffer become invalid (for example, overwritten by something else)

looking at the code to ReadBlock, it is clear that it is returning a pointer to new'd memory, and is expecting you to delete it when ever you are done with it. that buffer will never be overwritten or become invalid until you delete it.

speed wise, thats the other advantage to fsream.read's 'you sort out the buffer' approach: YOU get the choice on when memory is allocated. if you are going "read data, process, delete buffer, read data process delete buffer, ect.... " it is going to be alot more efficient to just allocate one buffer (to the maximum size you will need, this will be the size of your biggest single read) and just use that for everything, as suggested by Stephen.

How about using a static char* memblock; It will be initialised just once and it wont allocate memblock a new space everytime.

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.

Since c++11, one can use std::unique_ptr for this purpose.

From https://en.cppreference.com/book/intro/smart_pointers :

void my_func()
{
    int* valuePtr = new int(15);
    int x = 45;
    // ...
    if (x == 45)
        return;   // here we have a memory leak, valuePtr is not deleted
    // ...
    delete valuePtr;
}

But,

#include <memory>
 
void my_func()
{
    std::unique_ptr<int> valuePtr(new int(15));
    int x = 45;
    // ...
    if (x == 45)
        return;   // no memory leak anymore!
    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM