Resource management in programming languages

Resource management is very important if you want to write computer programs that behave properly. Resource here refers to anything that you would need to acquire and release inside your program, such as memory, file, network socket, etc. If the resources are not managed well, it may lead to resource leakage. Therefore, we need to ensure that resources are properly released under all circumstances. In this blog, I describe a few patterns used in different programming languages for resource management.

C++: RAII

RAII stands for resource acquisition is initialization. It means that in object-oriented languages, the lifetime of the resource should correspond to the object associated with the resource. Therefore, we could acquire the resource inside the constructor and release it inside the destructor. RAII is commonly used in C++, as object destructor is exception-safe in C++, meaning it will be called even if an exception is raised.

#include <fstream>

int main()
{
    std::ifstream myfile("/tmp/myfile");
    return 0;
}

In the example above, we pass the file path to the constructor so the resource is automatically acquired while creating the myfile object, and the file will be closed when the destructor is called because std::ifstream follows the RAII idiom.

Golang: defer

In Golang, there is no constructor and destructor. However, we could still manage the resources well with the defer statement. A defer statement inside Golang program indicates that you want something to be executed, but only at the end of the enclosing function. Just like the destructor in C++, defer in Golang is “exception-safe” (should I say “panic-safe”?) so that these defered statements will be called no matter if a function returns normally or panics.

package main

import "os"

func main() {
    myfile := os.Open("/tmp/myfile")
    defer myfile.Close()
}

With defer, you can ensure this file gets closed no matter what. However, you still need to remember to add the call to Close(). I feel that it’s less convenient compared to RAII in C++, but I guess this is the best you can do in Golang since there is only struct and interface in Golang and that Golang is garbage-collected.

Java: try-catch-finally and try-with-resources

Prior to Java 1.7, resource management is done with the try-catch-finally block. In the try-catch-finally pattern, you acquire the resources inside the try block and close them inside the finally block. The finally block will always be executed so the resources could be closed properly with and without any exception.

BufferedReader br = null;
try {
    br = new BufferedReader(new Filereader("/tmp/myfile"));
} catch (IOException e) {
    e.printStackTrace();
} finally {
    br.close();
}

With Java 1.7, a new mechanism called try-with-resources has been introduced. This removes the need to use the finally block and it requires the classes of the objects you created implement the AutoCloseable interface. The interface simply ensures that a close() function is implemented for a class.

try (BufferedReader br = new BufferedReader(new FileReader("/tmp/myfile"))) {
    br.readLine();
}

In my opinion, the way resources are managed is not as nice as how C++ and Go do it. You introduce a new level of indentation with each try block (if you code nicely of course). This could easily decrease code readability if you have a few nested try blocks because you need to open different resources at different stages of a function. I understand that Java, like Go, doesn’t have destructor for classes because it’s garbage-collected. However, the Go way of using defer just looks nicer. That being said, you don’t have to manually call close() with the new try-with-resources style, so there is no absolute winner on resource management between Go and Java.

Conclusion

In this blog post, I introduced a few ways resources are managed in different programming languages. The idea is not to come up with the best way how resource management should be done (although personally I like RAII the best), but rather to just let you know how things are done out there in some real programming languages. I hope you find this an interesting read. Let me know your own opinions on this topic!

References

 
comments powered by Disqus