3 ms·
Here's an alternate method of C exception handling: https://github.com/andrewrk/libsoundio/blob/4ce3429bdd9b08a01cb8f1b60c38a61dc5d818df/src/coreaudio.cpp#L411
by AndyKelley 11y ago
Here's an alternate method of C exception handling:
https://github.com/andrewrk/libsoundio/blob/4ce3429bdd9b08a01cb8f1b60c38a61dc5d818df/src/coreaudio.cpp#L411 https://github.com/andrewrk/libsoundio/blob/4ce3429bdd9b08a0...
It does not use macros or goto and I find that it makes the code easy to reason locally about.
In summary:
struct RefreshDevices {
// fields that require clean up
}
static void deinit_refresh_devices(struct RefreshDevices *rd) {
// clean up rd regardless of what state it's in
}
static int refresh_devices(struct SoundIoPrivate *si) {
struct RefreshDevices rd = {0};
if (error_occurred) {
deinit_refresh_devices(&rd);
return ErrorCode;
}
// ...
deinit_refresh_devices(&rd);
return 0;
}
Whenever the ownership of a resource changes to something other than the stack of refresh_devices, you just null it out and it won't get cleaned up.
If calling deinit on every exit path of the function is too much typing you can wrap that function in another function that calls deinit, and the function doing the actual work can just return an error code without worrying about cleanup.
- kbenson 11y agoExceptions as a programming language concept often include a change in control flow. While your method does "handle and exceptional situation", I don't think it could be said to be a general purpose way of doing exception handling in C, if you want to support the concept of changing control flow. While I recognize that you yourself may or may not have valid arguments about whether altering the control flow is a good idea, I don't think that affects whether this works as a solution for exception handling, in the general, PL concept sense.
- AndyKelley 11y agoI don't follow. You are saying that returning from a function early is not "changing the control flow"? What exactly is your criteria for "solution to exception handling"?
- kbenson 11y agoYou are testing and returning, and responsible for propagating the error in your example, and have a chance to forget to do that. That is what IMO keeps this from being a general purpose exception. That you could correctly check the error return in one subroutine, but forget to in it's parent is the issue. Each approach has it's benefits and drawbacks. Automatically jumping to a cleanup routine means you can't forget to handle it, but also obfuscates control flow. In any case, I view it as an integral feature of exception handling.