I am attempting to create C++ classes to encapsulate Vulkan initialization procedures (at a very basic level, I'm still learning), and the way I have the set up requires the vulkan device to be passed to an explicit "destroy" function for cleanup to occur. I have all the initialization surrounded in a try-catch block; with the issue being that if an exception is thrown during initialization, the objects are destroyed and I can't call my "destroy" functions.
In psuedo code:
try{
DeviceObject device; // constructor initializes
SomeResource resource(device);
OtherResource other(device); // suppose an exception is thrown here
while(programRuns){
// do something
}
// end of program
other.destroy(device);
resource.destroy(device);
device.destroy();
}
catch (myException e){
showError(e);
}
In this case, my destroy functions aren't called if an exception is thrown during runtime, and they are only called after a successful program termination.
I have thought of a few different ways of setting things up to handle this situation and make sure the resources are explicitly cleaned up, but my question is: do I have to? I know that I "should", but will the OS handle cleaning up my created resources if the program crashes and exits or will it leave hanging junk on the system GPU (or something like that)?
Typical OSes (including Windows, Linux, Android, etc.) will clean up all of a processes's resources when the process is destroyed. That includes reclaiming any memory exclusively owned by that process, closing files and network connections opened by the process, decrementing reference counts on shared resources, etc. That includes destroying GPU contexts and any memory or other resources associated with them. So no, you won't be leaking system resources by not cleaning up when your program crashes.
In fact, some programs deliberately choose not to clean up on clean/intentional exit either, since the OS is often faster at this than calling a bunch of app termination code. Kind of by definition that code isn't frequently used, so may not ever have even been paged in from disk, and it often ends up doing more work than just releasing OS-level resources, e.g. calling destructors for objects that don't own OS-level resources.
The main reason to clean up gracefully on exit (either clean or crash) is so that leak detection tools can help you find non-termination leaks. If you leak everything, reports about resources you leaked pre-termination -- which might indicate problematic indefinitely-growing leaks -- tend to get lost in the noise.