1

Today, without much thought, I wrote a simple function return to a char* based on a switch statement of given enum values. This, however, made me wonder how I could release that memory. What I did was something like this:

char* func()
{
    char* retval = new char[20];
    // Switch blah blah - will always return some value other than NULL since default:
    return retval;
}

I apologize if this is a naive question, but what is the best way to release the memory seeing as I cannot delete the memory after the return and, obviously, if I delete it before, I won't have a returned value. What I was thinking as a viable solution was something like this

void func(char*& in)
{
    // blah blah switch make it do something
}

int main()
{
    char* val = new char[20];

    func(val);
    // Do whatever with func (normally func within a data structure with specific enum set so could run multiple times to change output)

    delete [] val;
    val = NULL;
    return 0;
}

Would anyone have anymore insight on this and/or explanation on which to use?

Regards,
Dennis M.

RageD
  • 6,693
  • 4
  • 30
  • 37
  • Your second code example doesn't make any sense. You return in a void function assign a character value to a pointer, have a reference to a pointer (valid but not often usefull). – Winston Ewert Dec 26 '10 at 17:20
  • Sorry, typo. There should be no return. – RageD Dec 26 '10 at 17:28
  • By the way, if you're returning a `char *` I suppose you need to return a string instead of a single character, and in that case you should use `new char[size]`/`delete []`. – Matteo Italia Dec 26 '10 at 17:32
  • Yes, I apologize for the typos in the second example. I wrote it on the fly at the time of this post just very briefly without checking it over. – RageD Dec 26 '10 at 17:34
  • @Raged : there is still problem. It's not typo. It's that you don't know `val = NULL;` before `delete val;` doesn't make sense! – Nawaz Dec 26 '10 at 17:50
  • @Nawaz: Sorry, again this edit was made in haste (had a busy day today, was in and out). You can see before that, in my original edit, I simply just added the line afterward. I have revised the OP and there should be no errors in the second example. My apologies. – RageD Dec 27 '10 at 01:06

4 Answers4

2

Have you considered using an STL type or other class instead of returning a raw pointer? For instance, if your char * is a string, use std::string instead and avoid any risk of leaks:

std::string func()
{
    std::string retval("");

    // Switch blah blah - will always return some value other than NULL since default:

    return retval;
}
Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
2

You could write such functions in pair, like

Xyz* CreateXyz();
void DestroyXyz(Xyz *xyz);


Abc* NewAbc();
void DeleteAbc(Abc *abc);

Or you simply can transfer the responsibilty of deleting Xyz/Abc to the clients, i.e ones who call the function must also do delete on the returned object after using it.

Whatever you choose, make it clear in your documentation how the created object should be destroyed.

I would prefer pair-functions, especially if there is lot of things to consider before deleting!

By the way, you should prefer using std::string, instead of char*. Make use of STL as much as you can. They can solve most of your problems! The above advice is for situations where STL doesn't fit! In general, prefer STL!

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Thanks! I do often use STL, however, I was just wondering in this case how to make this work. Awesome solution. – RageD Dec 26 '10 at 17:30
  • 1
    I would add that creating a class to hold the resource (and release it in the destructor) is often better. So create XYZ and ABC classes rather then New/Delete functions for them. – Winston Ewert Dec 27 '10 at 00:33
  • @Winston Ewert: that is also good. but if one creates use-and-throw kind of objects and that too frequently, then it's better to have pair-functions (as described in my post) in your design, so that users can destroy an object immediately, after using it. – Nawaz Dec 27 '10 at 10:02
  • @Nawaz, I'm not sure what you mean use-and-throw. I'm assuming you mean that you create the object, use it for a short period of time, and then get rid of it. (I'd suggest throw isn't a good choice of terminology for that because throwing is used for exceptions.) However, in that case I want to create an object on my stack so that its automatically destroyed when the function ends. I'm not seeing how using the paired functions would be better there. – Winston Ewert Dec 27 '10 at 18:32
  • @Winston Ewert: IF he wants to return the object from a function, in that case pair-functions make sense. This is another scenario: http://stackoverflow.com/questions/4555961/how-to-use-a-class-in-dll/4556092#4556092 – Nawaz Dec 29 '10 at 17:14
  • @Nawaz, there are three types of functions which are consideration here: Normal functions, creation functions, and deletion functions. Creation and deletion functions are paired the same code should call both of them. If a normal function creates an object, it should destroy it. However, if a normal function returns an object, it breaks the rules because now some other code must destroy the object. Any pair of creation/deletion functions can be converted into the constructor/destructor of a class. – Winston Ewert Dec 29 '10 at 18:58
  • Of course, sometimes you must return an object from your function. The creation/deletion pairing does not seem to help there. My own preference is to use some sort of reference counting smart pointer to make sure the object is destroyed when its no longer in use. Regarding the dll example, thats a valid example. However, I'd probably want to hide that detail of implementation. I'd probably use a static method to construct the object and use a smart pointer to ensure that my own deletion code gets run. – Winston Ewert Dec 29 '10 at 19:00
  • @Winston Ewert : did you read when I said "IF **he** wants to return the object from a function, in that case pair-functions make sense."?? – Nawaz Dec 29 '10 at 19:07
  • @Winston Ewert : Also did you see that link? – Nawaz Dec 29 '10 at 19:10
  • @Nawaz, I'm just not seeing the connection that you are between wanting to the return the object and the helpfulness of a pair function. Is the function you are talking about the Create*() function or some other function? – Winston Ewert Dec 29 '10 at 21:45
  • @Nawaz, ok, I think I see what you are saying now. If you must return an object from a function like that, yes, pairing is a good idea. My point was that its a rarely a good idea to return an object like that. (Your dll example being an exception) – Winston Ewert Dec 29 '10 at 22:01
  • @Winston : What you're discussing is design, you probably would not design the way topic starter have designed his code, but that is a different question altogether. I was merely suggesting him what to do next if he wants to return an object from a function, how to destroy it, etc. Anyway, as for his example, I would probably use `std:string`. No Create(),no Destroy(). :-) – Nawaz Dec 29 '10 at 22:09
  • @Winston : Since I would probably use `std::string`, so I kind of agree with what you said. It's just that I was focusing on his problem of freeing the memory than his design. Please note the name of this topic also. :-) – Nawaz Dec 29 '10 at 22:17
  • @Nawaz, but isn't having Create/Delete paired functions design also? I interpreted the question as being one of how to write code which avoid leaking stuff. The correct answer, as I think you'll agree, it almost always to encapsulate it an object. – Winston Ewert Dec 29 '10 at 22:45
  • @Winston: Yes, that is design also, but it's his design, not mine. He wrote a func() function (which is actually Create() function, so I just renamed it), and I suggested him if he is going to do that, then he better write another func2() called Destroy(). – Nawaz Dec 30 '10 at 04:20
  • @Winston : Correct answer could be many, as long as it serves it's purpose and doesn't leak memory. – Nawaz Dec 30 '10 at 04:22
2

If you plan to return raw pointers from a function, you must make really clear on the documentation whose is the responsibility of deleting the pointer, i.e. who owns it. In this case, you should state explicitly that the pointer ownership is transferred to the caller, who is responsible to delete it.

Although many people are OK with just specifying the ownership in the documentation, often it's better to enforce this policy in the code. In particular, smart pointers are often used for this: the current C++ standard provides the std::auto_ptr, a smart pointer which transfers ownership on copy, i.e. when you return it to the caller, you're transferring the ownership to the target std::auto_ptr. Notice that std::auto_ptr automagically deletes the pointed memory on its destruction if it still owns it. The upcoming C++ standard provides std::unique_ptr that works in a similar fashion, but using move semantic.

Unfortunately, std::auto_ptr isn't thought for arrays (which need delete [] instead of delete), so you cannot use for your your purpose. I think that the decision of not including an auto_ptr for arrays was made deliberately, because the STL already provides all the containers you may need if you need to return a collection of items which handle by their own memory management and copy.

In particular, for strings you should simply use std::string and forget completely about this kind of memory management and pointer ownership problems.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
0

In this case whoever calls the func() should release the memory when its not needed. But the correct deletion happens like this:

delete val;
val = NULL;
ismail
  • 46,010
  • 9
  • 86
  • 95