开发者

Three exception-handling Versions, which one is preferable?

开发者 https://www.devze.com 2023-01-17 19:28 出处:网络
I\'m implementing a Zip-Wrapper (zlib minizip) and asking myself how i should handle exceptions properly. I\'m thinking of three versions. Which one would

I'm implementing a Zip-Wrapper (zlib minizip) and asking myself how i should handle exceptions properly. I'm thinking of three versions. Which one would you prefer, or is there a version i didn't thought about?

The tas开发者_开发问答k of the function Install is to get a Zip-File from a Web-Server, unpack its content and delete the downloaded Zip-File. But if an error occurs while unpacking the file, where should the Zip-File be deleted?

Tanks for your experiences.

Version A (with deleting outside the function):

void Install() {
    getFile("upd.zip"); // Creates File
    MyZip myzip("upd.zip");
    myzip.unzip();      // Can't do its job --> Exception
    delete("upd.zip");  // In case of exception: File would not be deleted here
}

int main() {
    try {
        Install();
    }
    catch (const Error& err) {
        delete("upd.zip"); // File must be deleted here
        MessageBox(err.text);
    }
}

Version B (with Re-Throwing the exception)

void Install() {
    getFile("upd.zip"); // Creates File
    try {
        MyZip myzip("upd.zip");
        myzip.unzip();
    }
    catch (const Error& err) {
        delete("upd.zip");
        throw err; // Re-Throw the Error
    }
    delete("upd.zip");
}

int main() {
    try {
        Install();
    }
    catch (const Error& err) {
        MessageBox(err.text);
    }
}

Version C (with return code)

void Install() {
    getFile("upd.zip"); // Creates File
    MyZip myzip("upd.zip");
    if (!myzip.unzip("upd.zip")) {
        delete("upd.zip");
        throw Error(myzip.geterror()); // what was the reason
    }
    delete("upd.zip");
}

int main() {
    // Same as in Version B
}


None of the three. Use RAII:

class FileGuard {
public:
    FileGurad(const std::string & filePath)
    : m_FilePath( filePath )
    {}

    ~FileGuard() {
        delete(m_FilePath); // must not throw an exception
    }
private:
    std::string m_FilePath;
};

Usage:

void Install() {
    guard FileGuard(getFile("upd.zip")); // Creates File; getFile should return the path where the file was created
    MyZip myzip("upd.zip");
    myzip.unzip();      // Can't do its job --> Exception
    // file will be deleted when guard goes out of scope (e.g. when an expection is thrown)
}

Alternatively you can have FileGuard call getFile in the constructor. See this answer (and others to the same question) for more information about stack unwinding (esp. the order of destruction).

0

精彩评论

暂无评论...
验证码 换一张
取 消