0

I hope this question is not too subjective.. all I want is good design that would prevent memory leaks happening later in my code. I coulnd't find any question on SO. I always found questions about what to do after allocating data in function which is not my case.

Also for some reason I am not using newer C++ standards like C++11 (shared pointers).

Let me demonstrate by example:

I have logic of data buffering which are later being sent. The buffering is done in one class and sending in another class.

In one point of code I am taking some data from buffer, process it (check the type of data etc) and then send it with function send:

bool send_data(char *data, size_t data_length) {

The data are consumed and are no longer needed. Shall I free them in the send_data or shell I leave that to the caller?

  1. Free it inside:

    bool send_data(char *data, size_t data_length) {
      //... process data ...
      send(data, data_length, ...);
      delete[] data;
    }
    
  2. Leave it and let the caller free it:

    send_data(data,data_length);
    delete[] data;
    

Or is there a design flaw and I should do something totally different?


The reason for not using C++11 is that the code is big & old - should I rewrite it completely? But I am considering to rewrite just some parts of the code because something is better then nothing.

And also the usage of some pointers spans lots of places of code I would have to change them all. Sometimes its not so easy to find them all because the usage may be hidden by casting and the buffering etc.

The data buffering is important. I have lot of data in buffers not just one char array. I am not sure if the data can be made static as some of you have in answers.. I will think about it.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
nayana
  • 3,787
  • 3
  • 20
  • 51
  • Or 3: Use [a container](http://en.cppreference.com/w/cpp/container) (or [a string](http://en.cppreference.com/w/cpp/string/basic_string)) so that you don't have to manually handle those things. – Some programmer dude Dec 14 '15 at 09:53
  • @JoachimPileborg thanks, but I cannot because of [this](http://stackoverflow.com/questions/34227436/how-to-map-structure-to-char-proper-method-in-c) check edit on accepted answer – nayana Dec 14 '15 at 09:57
  • I disagree with what you chose as the accepted answer over there. If you want to do it in a clean manner you need to follow a standard object serialization paradigm. It avoids potential bugs. Like, for example, how the answer you chose (and, from the looks of it your old code as well) isn't endian-safe. – KarenRei Dec 14 '15 at 10:05

3 Answers3

3

If you don't want to use c++11, you can use std::auto_ptr, or if you can actually, use std::unique_ptr. But as I see, it seems like you are using char * for, may be, an array. If so, don't use smart pointers (at least without custom deallocators) and call delete[] instead of delete. Also, if you need to pass a char *, you can use

std::vector<char> vec;
vec.push_back(...);
//...
send_data(&vec[0], vec.size());

If you are sure you strongly want to use char *, delete it in the caller, it is far better practice. Because who allocates memory is it's owner, so owner deletes it. Also it removes a side effect from callee, and makes it callee easier to use for other developers, who won't expect i.e that send_data will also delete their data.

V. Kravchenko
  • 1,859
  • 10
  • 12
  • good point about delete.. yes its array and it should be delete[], I will change the question to not confuse others. I like the vector option.. I will think about it.. also thanks for the last hint, can you also elaborate on why its best practise? – nayana Dec 14 '15 at 10:08
  • I accept this one because of vector and reason why the caller(owner) should delete. Thanks – nayana Dec 14 '15 at 10:40
1

If you want good design to prevent memory leaks, the answer is to use a container, and there are plenty of containers to chose from that don't require C++11. If you want it to be as "freeform raw data" as possible, then yes, you should use a newer standard and use unique or shared pointers - is there any particular reason you're still stuck in the last decade compiler-wise?

If you want to handle it the C way (which is what you're insisting on doing above), then it's really application dependent. If you meet the following constraints:

1) Only one thread will use the data at a time 2) The data size is never prohibitive 3) There's nothing else that would make it unreasonable to leave it sticking around

... then I recommend storing it in a static pointer, wherein nobody ever needs to free it. That's what a lot of the stdlib library functions do when they deal with strings.

KarenRei
  • 589
  • 6
  • 13
  • Hi thanks for the answer.. yes I am considering c++11 the main reason why not is big codebase.. it was all written in old style c++ way.. using new stuff like shared pointers may confuse the other parts of code (little joke). I think I cannot use static.. I am doing buffering(check update2 on bottom) from multiple threads and there is lot of data which are flowing through the buffers – nayana Dec 14 '15 at 10:31
1

C++ style would be to use the safe ptr wrappers.

C style, as here, means definitely leave it to the caller.

The call could be:

char data[256];
...
send(data, sizeof(data);

So no delete[] data

To be a bit more safe, you could hide the original send and manage data and its deletion separately. C++ as class, C style as a couple of functions.

struct Data {
    char* data;
    size_t size;
};

void send(struct Data* data) {
    if (!data->data) {
        throw new IllegalStateException("...");
    }
    _send(data->data, data->size);
    delete[] data->data;
    data->data = NULL;
}
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • but the data are buffered in dequeue from various places and then picked up and sent.. do you think its good idea to go static? the second snippet of code looks like exactly what I have, just imagine that I have dequeue of struct Data and your send function is much bigger and contain som Data processing logic.. so I take it as "leave it to caller" as you delete after _send call – nayana Dec 14 '15 at 10:24
  • I meant the usage _could_ pass a static or stack allocated array - for the `send` coder. But just renaming the method to **`send_and_delete`** would be good style too. – Joop Eggen Dec 14 '15 at 10:28
  • 1, The code is multithreaded I would have to synchronise the buffering and sending.. in order to be able to fill in another data to the static buffers(or am I thinking in a different way than you?). THere is QoS mechanism which needs to have more data in buffers.. I cannot have just one packet per time in buffers.. Otherwise I would have to have big static buffers with circular buffer mechanism over it which I think is not good or desirable.. 2, I have been told many times - "dont have functions which do two things" .. so I think that I would rather leave the deletion to the caller. Thanks. – nayana Dec 14 '15 at 10:38
  • @JoopEggen Calling a function like `doA_and_doB` is not a good style. – V. Kravchenko Dec 14 '15 at 11:01
  • That was why I answered in the first spot: leaving the deletion to the caller is more than nice style. Point 2 / @V.Kravchenko is very valid, but in this case a kind of `consume()` function would not be that bad: redundancy of always calling `delete[]` after a `send` would be prevented. One could argue here that a queue like consume is intended. – Joop Eggen Dec 14 '15 at 11:04