0

I want to write a library with "no resource leak guarantee" feature. So I shall know whether each method allocates any resource or not. It may change the code. For example:

void foo()
{
  methodDontAllocateAnyResources();
  methodCanThrow();
}

void bar()
  methodAllocateSomeResources();
  try{
    methodCanThrow();
  }
  catch(const std::exception& exp){
    releaseAllocatedResources();
    throw;
  }
}

Both foo() and bar() functions can throw an exception. It doesn't matter because I let exceptions to propagate. But In bar(), I must catch a possible exception to avoid a resource leak.

In the example I could decide to use or not a try-catch block easily. However, you know, normally we cannot understand whether a method allocates any resource or not by its name. So, I've decided to put this information into method documentation. Doxygen doesn't have such a tag. Also, I cannot find any web resources suggest that. Do you think using a custom @resource-allocation tag is a good idea?

Thanks

1

I want to write a library with "no resource leak guarantee" feature. [...] It doesn't matter because I let exceptions to propagate. But In bar(), I must catch a possible exception to avoid a resource leak.

This sounds good, all the way to the last sentence.

Consider using RAII resources and smarter return types to manage resources, instead of internal try/catch blocks.

Alternative implementation for bar:

struct raii_resource {
{
  raii_resource(type value) : value_{value} {}
  ~raii_resource() { releaseAllocatedResources(value_); }
  type value_;
}; 

void bar() {
  raii_resource r = methodAllocateSomeResources(); // returns type instance
  methodCanThrow();
}

If your function needs to return the allocated resource to the client code, simply wrap the return value in a smart wrapper (that will delete it at the end of scope).

Usually, in C++ you should only use try/catch blocks to handle errors, not to release allocated resources.

If you do this (use raii), the documentation of allocated resources will become irrelevant, because resource leaks are no longer possible.

That said, to add allocations information to the API documentation, I would add it as a @remarks or something similar.

  • Using RAII technique, the resource will be released if bar is completed successfully or throws an exception. But, I may want to use the resource outside bar then release it in another method. For example, in your bar r may be assigned to a member variable. – Q Q Jan 7 '15 at 11:27
  • 1
    @QQ: If bar transfers ownership of the resource to a member, then that member (or the class that contains it) becomes responsible for ensuring the resource isn't leaked. Most smart wrappers can deal with that scenario without trouble. – Bart van Ingen Schenau Jan 7 '15 at 11:46
  • I read some articles on RAII. If I took correct, according to RAII r should not be allocated in bar. It should be allocated in the constructor of the class which bar belongs to. (I suppose we want to use r after bar finished.) Now, the object encapsulating r became a resource too. (Because, it has a resource and needs cleanup after use). End of the day, I shall allocate every possible needed resources in a single constructor when I write an application in RAII style. I think it is not a suitable solution. – Q Q Jan 7 '15 at 13:36
  • @QQ, if the resource is to be released outside of the function, return a class instance that wrapps the resource and releases it at the end of it's lifetime. – utnapistim Jan 7 '15 at 13:39
  • @QQ, it seems to me you don't grok RAII. A "resource" is something that will need to be released/cleaned-up. If the object encapsulating r cleans it up in it's destructor, that object doesn't "become a resource", and it doesn't need anything extra for cleanup (it's destructor will be called automatically in stack unwinding). Also, do not allocate resources in constructors, but outside constuctors, and pass them to constructors already allocated (as in my example above). – utnapistim Jan 7 '15 at 13:49
1

your goal : "no resource leak guarantee"

your propsed solution: using a custom @resource-allocation tag to document all possible resource allocations

I donot think that the idea to document resource allocation will help you to avoid resource leaks.

the chances that you forget to add the resource-documention-tag is at least as high as the chance that you forget to release a resource in a catch or finally block.

In my opition it would be better to have a declarative way to avoid resource leaks like c++ smart pointers.

java and c# have a declarative language construct "using" that takes care of resource-deallocation:

 using (MyResource r = new MyResource()) {
    doSomeThingWith(r);
 }

The compiler translates this into something like (java syntax. c++ syntax should be similar)

 MyResource r = null;
 try {
    r = new MyResource();
    doSomeThingWith(r);
 } finally {
    if (r != null) delete r;
 }

I donot know if there is something similar to "using" in the c++ world.

  • In C++, the equivalent would be { std::scoped_ptr<MyResource> r(new MyResource()); doSomethingWith(r); }, with the resource being cleaned up by std::scoped_ptr. – Bart van Ingen Schenau Jan 7 '15 at 10:54
0

Simply adding tags where you allocate resources just documents where the leaks are likely to occur. It doesn't actually prevent the leak.

Use RAII when allocating leakable resources - acquire them only in constructors, and then free them in the corresponding destructors. Watch out for constructors that can throw exceptions. Either add exception handlers within the constructor to tidy up any already acquired resources, or else wrap each resource in a simple class that does its own RAII.

Beware of raw pointers - when a pointer goes out of scope, it doesn't release the thing it's pointing to. Prefer storing your RAII-wrapped reources by value, or using smart pointers which will free up the thing they point to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.