How to remove allocated memory and return its value from method

I have this function as part of a class that I am writing:

const char* sockets::TCPSocket::doRecv(int flags)
{
    char* incomingDataBuffer = new char [this->bufferSize];
    ssize_t bytesReceived    = recv(this->filedes, incomingDataBuffer, this->bufferSize, flags);

    // TODO set timeout - If no data arrives, the program will just wait here until some data arrives.
    if (bytesReceived == 0 || bytesReceived == -1)
    {
        // TODO error handling
    }

    // TODO avoid memory leak
    // delete[] incomingDataBuffer;
    // incomingDataBuffer = 0;


    return incomingDataBuffer;
}

      

As you can see, my problem here is that I need to dynamically allocate the buffer size for my input string, and I would like to return that value to the user. I don't want to leave it to the user to free that memory later, as it seems like bad encapsulation.

My instinct is to create a static copy of the inDataBuffer c string and return it to my user. However, despite some hard searching, I have not been able to find a general way to do this, which makes me think I am simply wrong.

Clearly I have other options.

  • I could make incomingDataBuffer a member of the class and then handle deleting it in the destructor, but that somehow doesn't seem right as it has no other reason to be a member of the class.

  • I believe I can iterate over the array and convert it to a vector that can be returned and converted to a string. But again, this is not entirely correct, since the incoming DataBuffer can be quite large in some cases, and such an action can be quite costly.

Anyway, I guess this must be a common problem with the standard approach, so what is the correct C ++ way?

+3


source to share


3 answers


The standard C ++ way is to use std::vector

:

std::vector<char> sockets::TCPSocket::doRecv(int flags)
{
    std::vector<char> incomingDataBuffer(this->bufferSize);
    ssize_t bytesReceived = recv(this->filedes, 
        &incomingDataBuffer[0], this->bufferSize, flags);

    // TODO set timeout - If no data arrives, 
    // the program will just wait here until some data arrives.
    if (bytesReceived == 0 || bytesReceived == -1)
    {
        // TODO error handling
    }

    // on success, do this so that call site knows how much data
    // there actually is
    incomingDataBuffer.resize(bytesReceived);
    return incomingDataBuffer;
}

      



Since it vector

manages its own memory, there is no memory leak problem here. By returning it, you simply transfer responsibility for memory management to the caller, but the caller does not need to do anything. When vector

out of scope, memory delete

d is automatically.

+1


source


In C ++ one can use std::unique_ptr[]

.

std::unique_ptr<const char[]> sockets::TCPSocket::doRecv(int flags)
{
    std::uniqure_ptr<char[]> incomingDataBuffer(new char [this->bufferSize]);
    ssize_t bytesReceived    = recv(this->filedes, incomingDataBuffer.get(), this->bufferSize, flags);


    return incomingDataBuffer;
}

      



std::unique_ptr<char[]>

makes delete []

a destructor in it, and its return from the function does not copy the data (since it just moves).

0


source


Just use std::vector<char>

instead of dynamically allocated buffer:

std::vector<char> incomingBuffer(this->bufferSize);
ssize_t bytesReceived    = recv(this->filedes, incomingDataBuffer.data(), this->bufferSize, flags);
// Other stuff
return incomingBuffer;

      

This way, the memory is dynamically freed when the vector leaves scope on the client side. With C ++ 11 and move semantics, there won't be an expensive copy of the vector either. In general, try to avoid explicit insertion / deletion in modern C ++, which is what STL containers are for.

Just for completeness: another alternative would be to use std::unique_ptr<char[]>

, but for arrays its syntax is std :: vectors below in my opinion.

0


source







All Articles