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.
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!
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;
}
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.
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;
Related
I'm studying C++ and in all my "experiments" i'm trying to understand temporary objects (rvalues) lifetime.
My question is:
Having an object which contains a const char* pointer, what happens when i want to use a constructor which takes "const char*" as argument? Usually temporary objects get destructed automatically but what happens with pointers created in this way?
I'm not using std::string or other c++11 classes for now because I'm just focusing on understanding rvalueness.
An example below:
class MyAwesomeClass {
private:
const char* data;
public:
MyAwesomeClass(const char* ptr) {
this->data = ptr;
}
MyAwesomeClass(MyAwesomeClass&& myAwesomeClassRVALUE) {
this->data = myAwesomeClassRVALUE.data;
myAwesomeClassRVALUE.data = nullptr;
}
~MyAwesomeClass() {
delete data;
}
};
int main() {
MyAwesomeClass s = "My Awesome Class' string data.";
return 0;
}
Usually temporary objects get destructed automatically but what happens with pointers created in this way?
Pointers are objects themselves. Same thing happens to temporary pointer objects as happens to all other temporary objects.
Your example deletes a pointer pointing to a string literal, so the behaviour of the program is undefined. The class would also have a broken assignement operators even if it was used correctly by passing pointer to an array allocated with new[].
As for rvalueness, the only rvalue expression in the example that I could find is nullptr.
Note this answer is based on a previous edit of the question where MyAwesomeClass was a String class.
Your String class is not really a string class as it doesn't own the underlying string data. It's more akin to std::string_view.
You have two avenues I can see you can pursue:
Your class owns the underlying data. In this case the class is a wrapper around std::string and has std::stringdata member. Look up composition. No need to worry about lifetime asstd::string` is well behaved.
Your class is like a "pointer/reference/view" to another string. In this case you have a const char* and maybe std::size_t size data member. You basically have a std::string_view (except for the wisdom, expertise and experience that went into designing std::string_view). Since you don't own the underlying data you can't do anything about the lifetime of the underlying data. The user of the class must make sure it doesn't end with a "YourStringView" to an expired object, just as he/she needs to make sure it doesn't end up with a reference/pointer to an expired object.
The semantics of these two scenarios are wildly different (as the difference between an object and a pointer to an object).
Anyway I wouldn't recommend you do any of this except for maybe learning reasons. std::string_view already exists so just use that. If you want the printing capabilities use the fmt library or the C++ format library (that is based on the mentioned fmt library).
Even if you decide to do this for learning purposes I highly encourage you look into these alternatives and learn from how they are doing things.
MyAwesomeClass(const char* ptr)
{
this->data = ptr;
}
~MyAwesomeClass()
{
delete data;
}
Oh no, no, no! No!!
Please look into RAII and rule of 0/3/5. Your class either owns the pointed object or it doesn't. If it owns it then it is responsible for creating it and deleting it. If it doesn't then it can't do either. You can't have "half of responsibilities" where you are responsible for deleting it but not for creating it.
In user code you should never need to manually manage memory. Use the rule of 0.
Quick answer is that your class does not own the data, but just the raw pointer. Under certain conditions you will see a problem with delete operator. Raw pointer are not great tool to ensure correct object ownership.
I'm learning about std::unique_ptr, trying to grok what it represents.
Given a function (out of my control) that returns a unique_ptr, is it implied/well understood that each invocation returns a unique_ptr that points to a new object (different than any prior invocation)?
By way of example, the following code produces a double-free on exit, and I hope that I correctly understand why: unique_ptrs delete their underlying object on destruction; therefore two unique_ptrs encapsulating the same memory/object would cause a double-free on destruction of the second. Therefore, would the following implementation of function getUniquePtr() be commonly/implicitly understood to be unreasonable?
// main.cpp
#include <memory>
#include <iostream>
std::unique_ptr<int> getUniquePtr() {
static int* p = new int(42);
return std::unique_ptr<int>(p);
}
class PtrOwner {
public:
std::unique_ptr<int> p_;
};
int main( int argc, char* argv[] ) {
PtrOwner po1;
PtrOwner po2;
po1.p_ = getUniquePtr();
po2.p_ = getUniquePtr();
return 0;
}
It should be assumed that, if a function returns std::unique_ptr<T>, then the returned smart pointer points to an object that is not currently managed by anyone else. This does not necessarily mean that it always refers to a different object. So long as this convention is followed, double-free bugs will be avoided. If this convention is violated, double-free bugs will occur.
For example, if you see some function like this:
std::unique_ptr<T> foo(std::unique_ptr<T> arg);
This function might, potentially, return std::move(arg) under some circumstances or it might destroy arg and return some other pointer. (You have to read the documentation to know what it does). This implies that you could do something like this:
auto t = std::make_unique<T>();
t = foo(std::move(t));
t = foo(std::move(t));
In this case, foo might just return the same pointer value twice, and this is perfectly safe. This example seems silly, but hopefully it gets my point across.
Yes, your assumptions are (mostly) correct. A unique_ptr owns the object exclusively, which implies that no two unique_ptrs should point to the same object at any given time.
As others have pointed out, this does not guarantee that multiple invocations of the same function returns different objects. This is because you can pass ownership around (by moving it), so if you pass ownership back to a function, as in Brians answer, it may well return the same object again, without braking any rules.
If you decide to manage an object by using smart pointers, try to avoid new and delete altogether. To create an object T that is owned by a unique_ptr, use make_unique<T>. This avoids the error of creating multiple unique_ptr to the same object. A unique_ptr is not copyable for exactly this reason. In other words, your getUniquePtr should be implemented like this:
return std::make_unique<int>(42);
One of the few reasons to construct a smart pointer from a raw pointer (as opposed to using make_unique) is when you have existing code or a library that works with raw pointers, which you cannot change.
I wonder if there are any legitimate reasons to return unique pointers by reference in C++, i.e. std::unique_ptr<T>&?
I've never actually seen that trick before, but the new project I've got seems to use this pattern a lot. From the first glance, it just effectively breaks / circumvents the "unique ownership" contract, making it impossible to catch the error in compile-time. Consider the following example:
class TmContainer {
public:
TmContainer() {
// Create some sort of complex object on heap and store unique_ptr to it
m_time = std::unique_ptr<tm>(new tm());
// Store something meaningful in its fields
m_time->tm_year = 42;
}
std::unique_ptr<tm>& time() { return m_time; }
private:
std::unique_ptr<tm> m_time;
};
auto one = new TmContainer();
auto& myTime = one->time();
std::cout << myTime->tm_year; // works, outputs 42
delete one;
std::cout << myTime->tm_year; // obviously fails at runtime, as `one` is deleted
Note that if we'd returned just std::unique_ptr<tm> (not a reference), it would raise a clear compile-time error, or would force use to use move semantics:
// Compile-time error
std::unique_ptr<tm> time() { return m_time; }
// Works as expected, but m_time is no longer owned by the container
std::unique_ptr<tm> time() { return std::move(m_time); }
I suspect that a general rule of thumb is that all such cases warrant use of std::shared_ptr. Am I right?
There are two use cases for this and in my opinion it is indicative of bad design. Having a non-const reference means that you can steal the resource or replace it without having to offer separate methods.
// Just create a handle to the managed object
auto& tm_ptr = tm_container.time();
do_something_to_tm(*tm_ptr);
// Steal the resource
std::unique_ptr<TmContainer> other_tm_ptr = std::move(tm_ptr);
// Replace the managed object with another one
tm_ptr = std::make_unique<TmContainer>;
I strongly advocate against these practices because they are error prone and less readable. It's best to offer an interface such as the following, provided you actually need this functionality.
tm& time() { return *m_time; }
std::unique_ptr<tm> release_time() { return {std::move(m_time)}; }
// If tm is cheap to move
void set_time(tm t) { m_time = make_unique<tm>(std::move(t)); }
// If tm is not cheap to move or not moveable at all
void set_time(std::unique_ptr t_ptr) { m_time = std::move(t_ptr); }
This was too long of a comment. I don't have a good idea for requested use case. The only thing I imagine is some middle ware for a utility library.
The question is what do you want and need to model. What are the semantics. Returning reference does not anything useful that I know.
The only advantage in your example is no explicit destructor. If you wanted to make exact mirror of this code it'd be a raw pointer IMHO. What exact type one should use depends on the exact semantics that they want to model.
Perhaps the intention behind the code you show is to return a non-owning pointer, which idiomatically (as I have learned) is modeled through a raw pointer. If you need to guarantee the object is alive, then you should use shared_ptr but bear it mind, that it means sharing ownership - i.e. detaching it's lifetime from the TmContianer.
Using raw pointer would make your code fail the same, but one could argue, that there is no reason for explicit delete as well, and lifetime of the object can be properly managed through scopes.
This is of course debatable, as semantics and meaning of words and phrases is, but my experience says, that's how c++ people write, talk and understand the pointers.
std::unique_ptr does not satisfy the requirements of CopyConstructible or CopyAssignable as per design.
So the object has to be returned as a reference, if needed.
I'm trying to learn C++, and trying to understand returning objects. I seem to see 2 ways of doing this, and need to understand what is the best practice.
Option 1:
QList<Weight *> ret;
Weight *weight = new Weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return &ret;
Option 2:
QList<Weight *> *ret = new QList();
Weight *weight = new Weight(cname, "Weight");
ret->append(weight);
ret->append(c);
return ret;
(of course, I may not understand this yet either).
Which way is considered best-practice, and should be followed?
Option 1 is defective. When you declare an object
QList<Weight *> ret;
it only lives in the local scope. It is destroyed when the function exits. However, you can make this work with
return ret; // no "&"
Now, although ret is destroyed, a copy is made first and passed back to the caller.
This is the generally preferred methodology. In fact, the copy-and-destroy operation (which accomplishes nothing, really) is usually elided, or optimized out and you get a fast, elegant program.
Option 2 works, but then you have a pointer to the heap. One way of looking at C++ is that the purpose of the language is to avoid manual memory management such as that. Sometimes you do want to manage objects on the heap, but option 1 still allows that:
QList<Weight *> *myList = new QList<Weight *>( getWeights() );
where getWeights is your example function. (In this case, you may have to define a copy constructor QList::QList( QList const & ), but like the previous example, it will probably not get called.)
Likewise, you probably should avoid having a list of pointers. The list should store the objects directly. Try using std::list… practice with the language features is more important than practice implementing data structures.
Use the option #1 with a slight change; instead of returning a reference to the locally created object, return its copy.
i.e. return ret;
Most C++ compilers perform Return value optimization (RVO) to optimize away the temporary object created to hold a function's return value.
In general, you should never return a reference or a pointer. Instead, return a copy of the object or return a smart pointer class which owns the object. In general, use static storage allocation unless the size varies at runtime or the lifetime of the object requires that it be allocated using dynamic storage allocation.
As has been pointed out, your example of returning by reference returns a reference to an object that no longer exists (since it has gone out of scope) and hence are invoking undefined behavior. This is the reason you should never return a reference. You should never return a raw pointer, because ownership is unclear.
It should also be noted that returning by value is incredibly cheap due to return-value optimization (RVO), and will soon be even cheaper due to the introduction of rvalue references.
passing & returning references invites responsibilty.! u need to take care that when you modify some values there are no side effects. same in the case of pointers. I reccomend you to retun objects. (BUT IT VERY-MUCH DEPENDS ON WHAT EXACTLY YOU WANT TO DO)
In ur Option 1, you return the address and Thats VERY bad as this could lead to undefined behaviour. (ret will be deallocated, but y'll access ret's address in the called function)
so use return ret;
It's generally bad practice to allocate memory that has to be freed elsewhere. That's one of the reasons we have C++ rather than just C. (But savvy programmers were writing object-oriented code in C long before the Age of Stroustrup.) Well-constructed objects have quick copy and assignment operators (sometimes using reference-counting), and they automatically free up the memory that they "own" when they are freed and their DTOR automatically is called. So you can toss them around cheerfully, rather than using pointers to them.
Therefore, depending on what you want to do, the best practice is very likely "none of the above." Whenever you are tempted to use "new" anywhere other than in a CTOR, think about it. Probably you don't want to use "new" at all. If you do, the resulting pointer should probably be wrapped in some kind of smart pointer. You can go for weeks and months without ever calling "new", because the "new" and "delete" are taken care of in standard classes or class templates like std::list and std::vector.
One exception is when you are using an old fashion library like OpenCV that sometimes requires that you create a new object, and hand off a pointer to it to the system, which takes ownership.
If QList and Weight are properly written to clean up after themselves in their DTORS, what you want is,
QList<Weight> ret();
Weight weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return ret;
As already mentioned, it's better to avoid allocating memory which must be deallocated elsewhere. This is what I prefer doing (...these days):
void someFunc(QList<Weight *>& list){
// ... other code
Weight *weight = new Weight(cname, "Weight");
list.append(weight);
list.append(c);
}
// ... later ...
QList<Weight *> list;
someFunc(list)
Even better -- avoid new completely and using std::vector:
void someFunc(std::vector<Weight>& list){
// ... other code
Weight weight(cname, "Weight");
list.push_back(weight);
list.push_back(c);
}
// ... later ...
std::vector<Weight> list;
someFunc(list);
You can always use a bool or enum if you want to return a status flag.
Based on experience, do not use plain pointers because you can easily forget to add proper destruction mechanisms.
If you want to avoid copying, you can go for implementing the Weight class with copy constructor and copy operator disabled:
class Weight {
protected:
std::string name;
std::string desc;
public:
Weight (std::string n, std::string d)
: name(n), desc(d) {
std::cout << "W c-tor\n";
}
~Weight (void) {
std::cout << "W d-tor\n";
}
// disable them to prevent copying
// and generate error when compiling
Weight(const Weight&);
void operator=(const Weight&);
};
Then, for the class implementing the container, use shared_ptr or unique_ptr to implement the data member:
template <typename T>
class QList {
protected:
std::vector<std::shared_ptr<T>> v;
public:
QList (void) {
std::cout << "Q c-tor\n";
}
~QList (void) {
std::cout << "Q d-tor\n";
}
// disable them to prevent copying
QList(const QList&);
void operator=(const QList&);
void append(T& t) {
v.push_back(std::shared_ptr<T>(&t));
}
};
Your function for adding an element would make use or Return Value Optimization and would not call the copy constructor (which is not defined):
QList<Weight> create (void) {
QList<Weight> ret;
Weight& weight = *(new Weight("cname", "Weight"));
ret.append(weight);
return ret;
}
On adding an element, the let the container take the ownership of the object, so do not deallocate it:
QList<Weight> ql = create();
ql.append(*(new Weight("aname", "Height")));
// this generates segmentation fault because
// the object would be deallocated twice
Weight w("aname", "Height");
ql.append(w);
Or, better, force the user to pass your QList implementation only smart pointers:
void append(std::shared_ptr<T> t) {
v.push_back(t);
}
And outside class QList you'll use it like:
Weight * pw = new Weight("aname", "Height");
ql.append(std::shared_ptr<Weight>(pw));
Using shared_ptr you could also 'take' objects from collection, make copies, remove from collection but use locally - behind the scenes it would be only the same only object.
All of these are valid answers, avoid Pointers, use copy constructors, etc. Unless you need to create a program that needs good performance, in my experience most of the performance related problems are with the copy constructors, and the overhead caused by them. (And smart pointers are not any better on this field, I'd to remove all my boost code and do the manual delete because it was taking too much milliseconds to do its job).
If you're creating a "simple" program (although "simple" means you should go with java or C#) then use copy constructors, avoid pointers and use smart pointers to deallocate the used memory, if you're creating a complex programs or you need a good performance, use pointers all over the place, and avoid copy constructors (if possible), just create your set of rules to delete pointers and use valgrind to detect memory leaks,
Maybe I will get some negative points, but I think you'll need to get the full picture to take your design choices.
I think that saying "if you're returning pointers your design is wrong" is little misleading. The output parameters tends to be confusing because it's not a natural choice for "returning" results.
I know this question is old, but I don't see any other argument pointing out the performance overhead of that design choices.
I'm fairly new to C++ so this is probably somewhat of a beginner question. It regards the "proper" style for doing something I suspect to be rather common.
I'm writing a function that, in performing its duties, allocates memory on the heap for use by the caller. I'm curious about what a good prototype for this function should look like. Right now I've got:
int f(char** buffer);
To use it, I would write:
char* data;
int data_length = f(&data);
// ...
delete[] data;
However, the fact that I'm passing a pointer to a pointer tips me off that I'm probably doing this the wrong way.
Anyone care to enlighten me?
In C, that would have been more or less legal.
In C++, functions typically shouldn't do that. You should try to use RAII to guarantee memory doesn't get leaked.
And now you might say "how would it leak memory, I call delete[] just there!", but what if an exception is thrown at the // ... lines?
Depending on what exactly the functions are meant to do, you have several options to consider. One obvious one is to replace the array with a vector:
std::vector<char> f();
std::vector<char> data = f();
int data_length = data.size();
// ...
//delete[] data;
and now we no longer need to explicitly delete, because the vector is allocated on the stack, and its destructor is called when it goes out of scope.
I should mention, in response to comments, that the above implies a copy of the vector, which could potentially be expensive. Most compilers will, if the f function is not too complex, optimize that copy away so this will be fine. (and if the function isn't called too often, the overhead won't matter anyway). But if that doesn't happen, you could instead pass an empty array to the f function by reference, and have f store its data in that instead of returning a new vector.
If the performance of returning a copy is unacceptable, another alternative would be to decouple the choice of container entirely, and use iterators instead:
// definition of f
template <typename iter>
void f(iter out);
// use of f
std::vector<char> vec;
f(std::back_inserter(vec));
Now the usual iterator operations can be used (*out to reference or write to the current element, and ++out to move the iterator forward to the next element) -- and more importantly, all the standard algorithms will now work. You could use std::copy to copy the data to the iterator, for example. This is the approach usually chosen by the standard library (ie. it is a good idea;)) when a function has to return a sequence of data.
Another option would be to make your own object taking responsibility for the allocation/deallocation:
struct f { // simplified for the sake of example. In the real world, it should be given a proper copy constructor + assignment operator, or they should be made inaccessible to avoid copying the object
f(){
// do whatever the f function was originally meant to do here
size = ???
data = new char[size];
}
~f() { delete[] data; }
int size;
char* data;
};
f data;
int data_length = data.size;
// ...
//delete[] data;
And again we no longer need to explicitly delete because the allocation is managed by an object on the stack. The latter is obviously more work, and there's more room for errors, so if the standard vector class (or other standard library components) do the job, prefer them. This example is only if you need something customized to your situation.
The general rule of thumb in C++ is that "if you're writing a delete or delete[] outside a RAII object, you're doing it wrong. If you're writing a new or `new[] outside a RAII object, you're doing it wrong, unless the result is immediately passed to a smart pointer"
In 'proper' C++ you would return an object that contains the memory allocation somewhere inside of it. Something like a std::vector.
Your function should not return a naked pointer to some memory. The pointer, after all, can be copied. Then you have the ownership problem: Who actually owns the memory and should delete it? You also have the problem that a naked pointer might point to a single object on the stack, on the heap, or to a static object. It could also point to an array at these places. Given that all you return is a pointer, how are users supposed to know?
What you should do instead is to return an object that manages its resource in an appropriate way. (Look up RAII.) Give the fact that the resource in this case is an array of char, either a std::string or a std::vector seem to be best:
int f(std::vector<char>& buffer);
std::vector<char> buffer;
int result = f(buffer);
Why not do the same way as malloc() - void* malloc( size_t numberOfBytes )? This way the number of bytes is the input parameter and the allocated block address is the return value.
UPD:
In comments you say that f() basically performs some action besides allocating memory. In this case using std::vector is a much better way.
void f( std::vector<char>& buffer )
{
buffer.clear();
// generate data and add it to the vector
}
the caller will just pass an allocated vector:
std::vector buffer;
f( buffer );
//f.size() now will return the number of elements to work with
Pass the pointer by reference...
int f(char* &buffer)
However you may wish to consider using reference counted pointers such as boost::shared_array to manage the memory if you are just starting this out.
e.g.
int f(boost::shared_array<char> &buffer)
Use RAII (Resource Acquisition Is Initialization) design pattern.
http://en.wikipedia.org/wiki/RAII
Understanding the meaning of the term and the concept - RAII (Resource Acquisition is Initialization)
Just return the pointer:
char * f() {
return new char[100];
}
Having said that, you probably do not need to mess with explicit allocation like this - instead of arrays of char, use std::string or std::vector<char> instead.
If all f() does with the buffer is to return it (and its length), let it just return the length, and have the caller new it. If f() also does something with the buffer, then do as polyglot suggeted.
Of course, there may be a better design for the problem you want to solve, but for us to suggest anything would require that you provide more context.
The proper style is probably not to use a char* but a std::vector or a std::string depending on what you are using char* for.
About the problem of passing a parameter to be modified, instead of passing a pointer, pass a reference. In your case:
int f(char*&);
and if you follow the first advice:
int f(std::string&);
or
int f(std::vector<char>&);
Actually, the smart thing to do would be to put that pointer in a class. That way you have better control over its destruction, and the interface is much less confusing to the user.
class Cookie {
public:
Cookie () : pointer (new char[100]) {};
~Cookie () {
delete[] pointer;
}
private:
char * pointer;
// Prevent copying. Otherwise we have to make these "smart" to prevent
// destruction issues.
Cookie(const Cookie&);
Cookie& operator=(const Cookie&);
};
Provided that f does a new[] to match, it will work, but it's not very idiomatic.
Assuming that f fills in the data and is not just a malloc()-alike you would be better wrapping the allocation up as a std::vector<char>
void f(std::vector<char> &buffer)
{
// compute length
int len = ...
std::vector<char> data(len);
// fill in data
...
buffer.swap(data);
}
EDIT -- remove the spurious * from the signature
I guess you are trying to allocate a one dimensional array. If so, you don't need to pass a pointer to pointer.
int f(char* &buffer)
should be sufficient. And the usage scenario would be:
char* data;
int data_length = f(data);
// ...
delete[] data;