Every defer statement is ultimately pushing a lambda into some stack that is executed when the defer block is exited. With an exception of setjmp/longjmp, I can't think of an existing C construct with similar run-time complexity.
However, for some things you can only free/return resources if you successfully created that resource. At which point you would need to use something like a stack.