I have the following code:
void do_something(Image *image)
{
Image *smoothed = NULL;
Image *processed = NULL;
if (condition_met) {
smoothed = smooth(image);
processed = smoothed;
}
else {
processed = image;
}
...
delete smoothed_image
}
I was wondering if I can do the following and if this is the correct way. I am confused about setting another pointer from an auto_ptr object and whether that changes the ownership somehow.
void do_something(Image *image)
{
auto_ptr<Image *> smoothed;
Image *processed = NULL;
if (condition_met) {
smoothed = smooth(image); // This should own the pointer returned by smooth
processed = smoothed; // Is this OK? processed is not an auto_ptr
}
else {
processed = image;
}
...
// Destructor for the 'smoothed' variable should be called.
// The 'image' variable is not deleted.
}
Will the destructor get called as I intend it and is this the correct way to do this?
A few points to make. Assuming that the signature of the smooth function is
Image* smooth(Image*);
Then your code would minimally have to be changed to
void do_something(Image *image)
{
auto_ptr<Image> smoothed;
Image *processed = NULL;
if (condition_met) {
smoothed.reset(smooth(image)); // This should own the pointer returned by smooth
processed = smoothed.get(); // Maybe? Depends on what you're doing
}
else {
processed = image;
}
It's reasonable in some cases to pull the raw pointer out of a smart pointer as is done in by smoothed.get() above, but you have to understand that as written the pointer held by smoothed will be deleted at the end of the function, even though you've done something else with the raw pointer. Not enough information here to see if that's a problem, but it's a smell.
std::auto_ptr is now deprecated in favor of std::unique_ptr. The big reason for this is the way the contents of auto_ptr are moved:
std::auto_ptr<int> a = new int(5);
std::auto_ptr<int> b = a; // Copy? No!
In this code the pointer held by a has been transferred to b. a is no longer holding anything. This runs counter to how we usually think of copy behavior so it's easy to mess up.
C++11 introduced the concept of r-value references (there are loads of articles around the net explaining this, including What are move semantics?). Having r-value references allows unique_ptr to prevent data from being moved where it doesn't make sense.
std::unique_ptr<int> a = new(5);
std::unique_ptr<int> b = a; // Compile fail. Not copyable
std::unique_ptr<int> c = std::move(a); // OK, shows intent
With this available, it would be possible to update your smooth() function signature to
std::unique_ptr<Image> smooth(Image*) {
...
return newImage;
}
Which clearly instructs the caller that they should take ownership of of the returned pointer. Now you can say
unique_ptr<Image> smoothed;
...
smoothed = smooth(image);
Because a value returned from a function is an r-value (not bound to a variable yet), the pointer is safely moved to smoothed.
In the end, yes, using a smart pointer is preferable to calling delete. Just think through your design and try to be clear about pointer ownership.
Related
I'm interested in updating an old personal project to modern C++. I appreciate how RAII simplifies cleanup: instead of making a new object and remembering to delete it before every return point in a function, just make_unique and it will be destroyed appropriately. But I have one nitpick when comparing the generated assembly.
Say there's a class method that replaces one of its unique_ptr members with a new value:
// std::unique_ptr<int> MyClass::m_foo;
void MyClass::refresh_foo(int x) {
m_foo = std::make_unique<int>(x * 3 + 5);
}
This will create a new int, assign it to m_foo, and then delete the old value of m_foo. But that's not quite the same as the old behavior, which could delete the old value, then create a new one and assign it to m_foo:
// int *MyClass::m_foo;
void MyClass::refresh_foo(int x) {
delete m_foo;
m_foo = new int(x * 3 + 5);
}
From the Compiler Explorer, gcc, clang, and MSVC all generate less code for the old way than the new one. I understand why this is the case, since that's the order in which all expressions are evaluated; p = q; has to construct q first. And of course m_foo had an invalid value in between the delete and new lines. But is there a way I'm missing to have unique_ptr destroy its old value and then create a new one in one expression? A "replace_unique"? Seems like it would be helpful when dealing with large objects so two of them don't needlessly coexist.
Edit: To be clear, I'm just using int as a trivial example here. My actual use cases are with classes of my own or from a library. And m_foo.reset(new int(x * 3 + 5)); naturally has the same problem compared to the old way of doing things, since it too has to construct the new int before assigning it and deleting the previous one.
You can use unique_ptr::reset() to deterministically destroy the currently held object when you want. Update the unique_ptr with a nullptr pointer before then updating it with a new object pointer, eg:
// std::unique_ptr<int> MyClass::m_foo;
void MyClass::refresh_foo(int x) {
m_foo.reset(); // <- int is destroyed here
m_foo = std::make_unique<int>(x * 3 + 5);
}
I accepted the answer which calls m_foo.reset() before m_foo = std::make_unique<int>(...) because it's the simplest way to solve the problem as stated: destroying the original value before constructing the new one. However, that does result in an extra delete call which shouldn't be necessary and is less optimal than the "pre-modern" way of using raw pointers.
This method, at least in Compiler Explorer with -Ofast, avoids the second delete call, and only has one extra mov instruction compared to the old way (explicitly setting m_foo to nullptr before assigning its newly constructed value):
// std::unique_ptr<int> MyClass::m_foo;
void refresh_smart(int x) {
m_foo = nullptr;
auto new_foo = std::make_unique<int>(x * 3 + 5);
m_foo.swap(new_foo);
new_foo.release(); // no memory leak since it's null
}
As a reusable template function:
template<typename T, typename... Ps>
void remake_unique(std::unique_ptr<T> &p, Ps... args) {
p = nullptr;
auto new_p = std::make_unique<T>(args...);
p.swap(new_p);
new_p.release();
}
// std::unique_ptr<int> MyClass::m_foo;
void refresh_smart(int x) {
remake_unique(m_foo, x * 3 + 5);
}
bool CPythonNonPlayer::LoadNonPlayerData(const char *c_szFileName)
{
DWORD dwElements;
TMobTable *pTable = (TMobTable *) zObj.GetBuffer();
for(DWORD i = 0; i < dwElements; ++i, ++pTable)
{
TMobTable *pNonPlayerData = new TMobTable;
memcpy(pNonPlayerData, pTable, sizeof(TMobTable));
m_NonPlayerDataMap.insert(TNonPlayerDataMap::value_type(pNonPlayerData->dwVnum, pNonPlayerData));
}
return true;
}
My question is: what am I doing wrong? This leaks a lot of memory. After each call of this function, the application usage increases by 10MB.
The problem is not in this function. The problem is in the way you handle m_NonPlayerDataMap. This function transfers ownership of some objects to that map, and it's that map's responsibility to delete them when it's done with them. I'll bet it doesn't.
By the way, to avoid this kind of problem just don't do this. Don't use new unless you really need to. Instead, make the map a map of values rather than a map of pointers. If you can't figure out any way to make that happen, at least use smart pointers rather than raw pointers.
Use smart pointer wrappers to handle memory management for you, eg:
If using a version earlier than C++11:
#include <memory>
// std::auto_ptr is not container-safe!
typedef std::map<DWORD, TMobTable*> TNonPlayerDataMap;
TNonPlayerDataMap m_NonPlayerDataMap;
...
bool CPythonNonPlayer::LoadNonPlayerData(const char *c_szFileName)
{
DWORD dwElements = ...;
...
// I'm assuming this just returns a pointer to an existing memory
// buffer and is not actually allocating a new buffer. If it is,
// you need to free it when you are done copying it...
//
TMobTable *pTable = (TMobTable *) zObj.GetBuffer();
for(DWORD i = 0; i < dwElements; ++i, ++pTable)
{
std::auto_ptr<TMobTable> pNonPlayerData(new TMobTable);
// don't use memcpy! better would be to give TMobTable a copy constructor instead...
// std::auto_ptr<TMobTable> pNonPlayerData(new TMobTable(*pTable));
//
*pNonPlayerData = *pTable;
// if successful, release local ownership of the object.
// if failed, ownership will remain here and free the object when the auto_ptr goes out of scope.
//
if (m_NonPlayerDataMap.insert(std::make_pair(pNonPlayerData->dwVnum, pNonPlayerData.get())).second)
pNonPlayerData.release();
}
return true;
}
Alternatively, if you are using C++11 or later:
#include <memory>
// std::unique_ptr is container-safe!
typedef std::map<DWORD, std::unique_ptr<TMobTable>> TNonPlayerDataMap;
TNonPlayerDataMap m_NonPlayerDataMap;
...
bool CPythonNonPlayer::LoadNonPlayerData(const char *c_szFileName)
{
DWORD dwElements = ...;
...
// I'm assuming this just returns a pointer to an existing memory
// buffer and is not actually allocating a new buffer. If it is,
// you need to free it when you are done copying it...
//
TMobTable *pTable = (TMobTable *) zObj.GetBuffer();
for(DWORD i = 0; i < dwElements; ++i, ++pTable)
{
std::unique_ptr<TMobTable> pNonPlayerData(new TMobTable);
//
// or, if using C++14 or later:
// std::unique_ptr<TMobTable> pNonPlayerData = std::make_unique<TMobTable>();
// don't use memcpy! better would be to give TMobTable a copy constructor instead...
// std::unique_ptr<TMobTable> pNonPlayerData(new TMobTable(*pTable));
// std::unique_ptr<TMobTable> pNonPlayerData = std::make_unique<TMobTable>(*pTable);
//
*pNonPlayerData = *pTable;
// if successful, ownership of the object is transferred into the map.
// if failed, ownership will remain here and free the object when the unique_ptr goes out of scope.
//
m_NonPlayerDataMap.insert(std::make_pair(pNonPlayerData->dwVnum, std::move(pNonPlayerData)));
}
return true;
}
I'm having some difficulty calling a copy constructor I set up.
Image::Image(const Image& img) /* Copy constructor */
{
this->x = img.x;
this->y = img.y;
this->data = img.data;
}
I'm trying to call it with Image input = *new Image(GetInput());. GetInput() returns a Image*. Is there a way I can make the arguments match up?
Doing this :
Image input = *new Image(GetInput());
Results in a instant memory leak because the allocated memory is stored nowhere.
If GetInput() does not allocate the returned Image every time, you can just do :
Image input = *GetInput();
Else you'd better go with some smart pointer :
std::unique_ptr<Image> input { GetInput() }; // C++11
auto input = std::make_unique<Image>(GetInput()); // C++1y / C++14
A far better solution would be to completely avoid the use of any pointer, but I guess this go out of the scope of the actual question ...
Also, if Image::data is a dynamically allocated variable, you'll run into a lot of trouble if you simply copy the pointers like you do in your snippet.
*new Image(....) is a bad idea because the memory allocated by new is immediately leaked. You never delete that pointer.
You can probably write:
Image *p = GetInput();
Image input(*p);
You would have to check the GetInput() function to find out if the returned pointer needs deleting or not; if so, then follow up with a:
delete p;
Note: make sure Image has a correct copy-constructor (check the Rule of Three too).
If I understand you correctly, you want to copy the result of GetInput into a new variable. You can do that with
Image input(*GetInput());
However, what happens to the value returned from GetInput? The documentation of the function should tell you who owns that object and who's responsibility it is to delete it.
If the caller (that's you) owns the object, you might be better of by just copying the pointer instead of creating a new object:
Image *input = GetInput();
I am wondering how one would go about returning a new object from a C++ function. For example, I have a SQLite wrapper which used to mix in Objective-C and I modifying it to be purely C++.
So, for example:
list<char*> * SqliteWrapper::RunQuery(const char *query)
{
list<char*> * result = new list<char*>();
//Process query
return result;
}
the issue that I can see in this, is that who owns the object? The calling class or the class that created the object? What is worse, is that this is very prone to memory leaks. If the caller object does not delete the newly created object, the app will end up with a memory leak.
Now that I think about this, this would make a lot of sense:
int SqliteWrapper::RunQuery(const char *query, list<char*>& result)
{
//Process query
return errorCode;
}
Are there any other approaches to this? I have been a C# programmer for a while and only now am starting to work heavily with C/C++.
Many programmers do this:
If it is a pointer that is returned, I am being given the object's identity (it's location in memory is unique) I must manage that. I am responsible for deleting it.
(Pointer = my job)
references however let you pretend you are being passed the object, to look at and use. you are not responsible for deleting these, something else is.
BUT:
"Naked pointers" may be frowned upon for code like this (it's very subjective) so some would say use a "unique_ptr" to that, these can be moved, and delete what they point to when deleted (unless the stuff is moved out of them), by returning one and not using it, it will be deleted.
(tell me if you want me to flesh this out, see also "shared_ptr" if multiple things have a pointer, this will delete what it points to when the last shared_ptr pointing to it is deleted)
Addendum 1
unique_ptr<list<char*>> SqliteWrapper::RunQuery(const char *query)
{
list<char*> * result = new list<char*>();
//Process query
return make_unique<list<char*>>(result);
}
Remember you can only move, not copy unique_ptrs
Well. You are right.
First example would be a bad style, since in such a code is hardly readable and it is hard to track bugs in it.
Usually people use the second approach with reference.
In the same way you can use pointer, allocating the return object before function call.
Third approach would be to use class instead of function. It is convinient if your function does complicated process with many parameters. In this case you store result as a data member of the class and ownership is obvious:
class SqliteWrapper {
...
class ProcessQuery {
public:
ProcessQuery():fQ(0),fP1(0){}
SetQuery(const char *query){ fQ = query; }
SetP1(int p1){ fP1 = p1; }
...
list<char*> GetResult(){ return fR; } // copy
int Run();
private:
const char *fQ;
int fP1;
...
list<char*> fR;
}
...
}
int SqliteWrapper::Process::Run()
{
//Process query
return errorCode;
}
I am trying to implement a custom memory manager and I am wondering if there is a better way to implement this function, as when I am asked about void pointer arithmetic, several people thought that if I had a void* in C++, something was very wrong.
// allocates a page of memory.
void ObjectAllocator::allocatePage()
{
//if(OAStats_.PagesInUse_ >= Config_.MaxPages_)
//throw exception
void* buffer = ::operator new(OAStats_.PageSize_); // allocate memory, no constructor call.
// =============== Setup the PageList_ ===============
GenericObject* pNewNode = ::new(buffer) GenericObject(); // Construct GenericObject for the pagelist.
pNewNode->Next = PageList_->Next; // pNewNode points to wherever PageList_ pointed to.
PageList_->Next = pNewNode; // PageList_ points to pNewNode
pNewNode = NULL; // dont need this handle anymore
buffer = static_cast<char*>(buffer) + sizeof(GenericObject); // move pointer to point after the generic object.
// =============== Setup the FreeList_ ===============
for(int i=0;i<Config_.ObjectsPerPage_;++i)
{
static GenericObject* pPreviousNode = NULL; // static variable to hold the previous node
pNewNode = ::new(buffer) GenericObject(); // Construct GenericObject for the freelist.
pNewNode->Next = pPreviousNode;
pPreviousNode = pNewNode;
buffer = static_cast<char*>(buffer) + OAStats_.ObjectSize_; // move pointer by ObjectSize.
++OAStats_.FreeObjects_;
}
FreeList_->Next = pNewNode;
++OAStats_.PagesInUse_;
++OAStats_.Allocations_;
}
If you need a block of memory for for storing a string (8-bit ANSI), it makes sense to declare a pointer to that buffer as char and operate on it.
In your case, you need a block of memory that is a 'blob', it has no inherent type, so you correctly chose void* to represent that blob.
Now you need to increment that pointer by the size of some object. You cannot perform arithmetic on a void pointer for obvious reasons, so what do you do? Cast it. There is no shame in that.
In C++, on raw bytes, use a char*, and don't think any less of yourself. It's The Right Thing To Do (tm). Especially if you wrap it in a higher level construct, like you have.
There's nothing inherently wrong with the void*. However, what we often see is people coming from C who overuse void* when they should do something else. If you're managing raw memory blobs, then a void* is perfectly appropriate. However, there's rarely any other reason to do it.