O que você sabe sobre as garantias de segurança de exceções?
sobes.tech IA
Resposta da IA
As garantias de segurança de exceções determinam o comportamento de uma função no caso de ocorrer uma exceção. São distinguidos quatro níveis de garantias:
-
Garantia básica (Basic guarantee): Se a função lançar uma exceção, o programa permanece num estado válido. Os recursos não vazam (por exemplo, a memória é libertada), mas o estado exato dos objetos pode ser desconhecido. Mantém-se a possibilidade de continuar a trabalhar com a aplicação.
// Exemplo de garantia básica void basic_guarantee_function(std::vector<int>& vec, int value) { // Podem ocorrer exceções ao inserir vec.push_back(value); // Se ocorrer uma exceção, o vec pode estar num estado imprevisível (parcialmente modificado), // mas a memória alocada para o vec será libertada corretamente ao sair do escopo. } -
Garantia forte (Strong guarantee): Se a função lançar uma exceção, o estado do programa mantém-se igual ao que tinha antes da chamada. Todas as alterações são revertidas.
// Exemplo de garantia forte // Uso da idiomática Copy-and-Swap para garantir a garantia forte class Resource { int* data; size_t size; public: Resource(size_t s) : size(s), data(new int[s]) {} ~Resource() { delete[] data; } Resource(const Resource& other) : size(other.size), data(new int[other.size]) { std::copy(other.data, other.data + size, data); // Pode lançar uma exceção } Resource& operator=(Resource other) // Transferência por valor que causa cópia { swap(*this, other); // Não lança exceções return *this; } friend void swap(Resource& first, Resource& second) noexcept { using std::swap; swap(first.data, second.data); swap(first.size, second.size); } // ... outros membros }; void strong_guarantee_function(Resource& res, size_t new_size) { Resource temp(new_size); // Se aqui ocorrer uma exceção, res não mudará res = temp; // Usa o operador= sobrecarregado que garante a garantia forte } -
Garantia de não lançar exceções (No-throw guarantee): A função garante que não lançará exceções. Essas funções são marcadas com o especificador
noexcept.// Exemplo de garantia de não lançar exceções void no_throw_function() noexcept { // Não há operações que possam lançar exceções int a = 5; int b = 10; int c = a + b; } -
Garantia de falha (Failure guarantee): No contexto de segurança de exceções, às vezes é mencionado este nível, que significa que a função pode deixar o programa num estado indefinido, com possível fuga de recursos ou falhas. Isto é, na realidade, a ausência de garantias. Deve-se evitar tal comportamento.
A importância das garantias de segurança de exceções reside na criação de código fiável e previsível, que trata corretamente erros e recursos mesmo na ocorrência de exceções. A escolha do nível de garantia depende da criticidade da operação, do custo do rollback e da probabilidade de ocorrência de uma exceção.
Tabela comparativa de garantias:
| Garantia | Estado em caso de exceção | Integridade dos dados | Fugas de recursos |
|---|---|---|---|
| Básica | Válido, mas indefinido | Não garantido | Não |
| Forte | Não alterado (como antes da chamada) | Mantém-se | Não |
| Sem garantias | Nunca ocorre (sem exceções) | N/A | N/A |
| Falha (sem garantia) | Indefinido, possível dano ou falhas | Não garantido | Possível |