4

Consider the code

struct Resource
{
 Resource()
 {
 std::cout << "C";
 }
 ~Resource()
 {
 std::cout << "D";
 }
};
void allocate(Resource **p)
{
 *p = new Resource();
}
int main()
{
 Resource *p = nullptr;
 allocate(&p);
 std::unique_ptr<Resource> uptr(p);
 //stuff
}

Assuming that 'allocate' function is heavily used in legacy code in multiple call sites, the main function shows an attempt to use unique_ptr to manage the allocated resource. The problem occurs when another programmer on the team writes exception prone code after 'allocate' and before 'unique_ptr' gets to own it.

So, one solution that comes to my mind is to write code which leverages the comma operator as follows

std::unique_ptr<Resource> up((allocate(&p), p));

Is there another reasonable way to handle this situation? Basic problem is to make alllocation and ownership as an atomic operation.

starsplusplus
1,2633 gold badges19 silver badges32 bronze badges
asked Jan 15, 2014 at 15:53
8
  • In this specific case, you could have a function that just returns the pointer: Resource *allocate() { Resource *result; allocate(&result); return result; }, and then use that function: std::unique_ptr<Resource> up(allocate()); Is your real problem more general, and if so, can you edit your question to include cases that cannot be solved like that? Commented Jan 15, 2014 at 15:58
  • how about wrapping the allocate function such that, it'll return a moved std::unique_ptr? Commented Jan 15, 2014 at 15:58
  • As I mentioned, allocate is a heavily used function and I don't see changing it signature right away. So, in the sense it is a slow but steady adoptance of C++11 concepts in the product Commented Jan 15, 2014 at 15:59
  • 1
    @Chubsdad: Nobody suggested changing it. They're talking about wrapping it. But then your colleagues have to remember to use the wrapper rather than the original function, or the entire purpose is moot, and if they were aware enough of the problems you've described to remember to do that, then they wouldn't have written exception-prone code there in the first place! Commented Jan 15, 2014 at 15:59
  • Which means I need to change all the call sites. May be we will get there but not immediately... Commented Jan 15, 2014 at 16:01

3 Answers 3

2

For the smoothest transition, create an overload of allocate:

template <typename T>
void allocate(std::unique_ptr<T>* p) {
 T* raw;
 allocate(&raw)
 p->reset(raw);
}

Existing call sites will continue to work unchanged. When you update a call site, you replace the raw pointer with a unique_ptr, and remove whatever line frees the resource, but otherwise keep the code unchanged. (Replace places where the raw pointer is passed with .get().)

answered Jan 15, 2014 at 16:15
Sign up to request clarification or add additional context in comments.

2 Comments

I think I would simply return the unique_ptr by value and get rid of the weird "pass-pointer-to-return-value" calling convention.
@Casey well, he did say "smooth transition" - std::unique_ptr<Resource> uptr; allocate(&uptr); vs Resource* p; allocate(&p);
1

The typical way to do that is to return a unique_ptr from an overloaded function:

std::unique_ptr<Resource> allocate()
{
 return std::unique_ptr<Resource>(new Resource());
}
answered Jan 15, 2014 at 16:07

4 Comments

About the edit: Isn't the unique_ptr constructor called automatically?
the reason for downvote is, that the OP doesn't want to change the call signature.
Don't change the call signature then. This will work fine as an overload.
0

Frankly, I rather like your comma solution. Of course, you still need your forgetful exception-happy programmers to remember to use it, so it doesn't work as a catch-all fix.

In fact, on that basis, there isn't one.

answered Jan 15, 2014 at 15:58

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.