C++ - Tutorial 011. Exceptions

C++, throw, catch, exception

What is an exception? This is a situation that is not provided by the standard behavior of the program. For example, an attempt to access an element in the Vector class (which we discussed in the article about classes ), which does not exist. That is, there is a way out of the vector. In this case, you can use exceptions to interrupt the execution of the program. This is necessary because

  • As a rule in such cases, the author of the Vector class does not know how the user wants to use its class, and also does not know in which program this class will be used.
  • A user of the Vector class can not always control the correctness of this class, so he needs to report that something went wrong.

To resolve such a situation in C ++, you can use the exception technique.

Consider how to write an exception call when an element is attempted to access an element that does not exist in the Vector class.

double& Vector::operator[](int i)
{
    if (i<0 || size()<=i) throw out_of_range{"Vector::operator[]"};
    return elem[i];
}

Here, the out_of_range exception is used. This exception is defined in the <stdexcept> header file.

The throw statement passes control to the handler for out_of_range exceptions in some function that directly or indirectly calls Vector::operator[]() . In order to handle exceptions, you must use the try catch statement block.

void f(Vector& v)
{
    // ...
    try { // function block with exception
        v[v.size()] = 7; // attempt to access an element outside the vector
    }
    catch (out_of_range) { // catch the error out_of_range
        // ... error handling out_of_range ...
    }
    // ...
}

Invariants

Also, try catch blocks allow processing of several different exceptions, which introduces invariance into the operation of the C ++ exception mechanism....

For example, a vector class can create an invalid vector size when it is created, or it can not find free memory for the elements it will contain.

Vector::Vector(int s)
{
    if (s < 0) throw length_error{};
    elem = new double[s];
    sz = s;
}

This constructor can throw an exception in two cases:

  • If a negative value is passed as the size argument
  • If the operator new can not allocate memory

length_error - This is the standard exception operator, because the std library often uses exception data in its work.

Exception handling will look like this:

void test()
{
    try {
        Vector v(−27);
    }
    catch (std::length_error) {
        // processing of negative vector size
    }
    catch (std::bad_alloc) {
        // memory allocation error handling
    }
}

You can also create your own exceptions.

Types of Exceptions

All exceptions to the standard library are inherited from std::exception.

At the moment, there are the following types of exceptions:

  • logic_error
    • invalid_argument
    • domain_error
    • length_error
    • out_of_range
    • future_error (C++11)
  • runtime_error
    • range_error
    • overflow_error
    • underflow_error
    • system_error (C++11)
      • ios_base::failure (начиная с C++11)
  • bad_typeid
  • bad_cast
  • bad_weak_ptr (C++11)
  • bad_function_call (C++11)
  • bad_alloc
    • bad_array_new_length (C++11)
  • bad_exception
  • ios_base::failure (до C++11)

std::logic_error

An exception is defined in the header file <stdexcept>

Defines the type of object that will be thrown as an exception. He reports errors that are the result of incorrect logic within the program, such as a violation of a logical prerequisite or a class of invariants that can be prevented.

This class is used as the basis for errors that can only be determined at run-time.

std::invalid_argument

An exception is defined in the header file <stdexcept>

Inherited from std::logic_error. Defines an exception that must be thrown in case of an incorrect argument.

For example, MSDN gives an example when an object of the bitset class from the standard library

// invalid_arg.cpp  
// compile with: /EHsc /GR  
#include <bitset>  
#include <iostream>  
  
using namespace std;  
  
int main( )  
{  
   try   
   {  
      bitset< 32 > bitset( string( "11001010101100001b100101010110000") );  
   }  
   catch ( exception &e )   
   {  
      cerr << "Caught " << e.what( ) << endl;  
      cerr << "Type " << typeid( e ).name( ) << endl;  
   };  
}  
\* Output:   
Caught invalid bitset<N> char  
Type class std::invalid_argument  
*\ 

In this example, an incorrect string is passed, inside of which there is a character 'b', which will be erroneous.

std::domain_error

An exception is defined in the header file <stdexcept>

Inherited from std::logic_error. Defines an exception that must be thrown if the mathematical function is not defined for the argument that is passed to it, for example:

std::sqrt(-1)

std::length_error

An exception is defined in the header file <stdexcept>

Inherited from std::logic_error. Specifies the exception that must be given to the brochete when an attempt is made to implement an excess of the allowed limits for the object. As was shown for the vector size at the beginning of theи.

std::out_of_range

An exception is defined in the header file <stdexcept>

Inherited from std::logic_error. Defines an exception that must be thrown when it is outside the allowed range of object values. As it was shown for the range of values of the wind at the beginning of the article.

std::future_error

An exception is defined in the header file <future>

Inherited from std::logic_error. This exception can be thrown in the event that the function that operates in asynchronous mode and depends on the thread library failed. This exception has an error code that is compatible with std::error_code.

std::runtime_error

An exception is defined in the header file <stdexcept>

This is the basic exception for exceptions that can not be easily predicted and must be thrown during program execution.

std::range_error

An exception is defined in the header file <stdexcept>

The exception is used for errors when computing floating-point values when the computer can not process the value, because it is either too large or too small. If the value is an integral type, then underflow_error or overflow_error should be used.

std::overflow_error

An exception is defined in the header file <stdexcept>

The exception is used for errors in the calculation of floating point values of the integral type, when the number is too large a positive value.

std::underflow_error

An exception is defined in the header file <stdexcept>

The exception is used for errors when calculating floating point values of an integral type when the number is too large a negative value.

std::system_error

An exception is defined in the header file <system_error>

std::system_error is an exception type that is called by various functions of the standard library (usually functions that interact with the operating system, for example, the std::thread constructor), with the exception having the corresponding std::error_code .

std::ios_base::failure

An exception is defined in the header file <ios>

It is responsible for exceptions that are thrown when I / O functions fail.

std::bad_typeid

An exception is defined in the header file <typeinfo>

An exception of this type occurs when the typeid operator is applied to a null pointer of a polymorphic type.

#include <iostream>
#include <typeinfo>
 
struct S { // The type must be polymorphic
    virtual void f();
}; 
 
int main()
{
    S* p = nullptr;
    try {
        std::cout << typeid(*p).name() << '\n';
    } catch(const std::bad_typeid& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_cast

An exception is defined in the header file <typeinfo>

This exception occurs when an object cast is attempted in that type of object that does not include inheritance relations with it.

#include <iostream>
#include <typeinfo>
 
struct Foo { virtual ~Foo() {} };
struct Bar { virtual ~Bar() {} };
 
int main()
{
    Bar b;
    try {
        Foo& f = dynamic_cast<Foo&>(b);
    } catch(const std::bad_cast& e)
    {
        std::cout << e.what() << '\n';
    }
}

std::bad_weak_ptr

An exception is defined in the header file <memory>

std::bad_weak_ptr - the type of the object, generated as an exception by the constructors std::shared_ptr, which accept std::weak_ptr as an argument when std::weak_ptr refers to an already deleted object.

#include <memory>
#include <iostream>
int main()
{
    std::shared_ptr<int> p1(new int(42));
    std::weak_ptr<int> wp(p1);
    p1.reset();
    try {
        std::shared_ptr<int> p2(wp);
    } catch(const std::bad_weak_ptr& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_function_call

An exception is defined in the header file <functional>

This exception is generated if the std::function() method of the std::function object was called, which did not receive the function object, that is, it was passed as the initializer nullptr, for example, and the function object was not was transferred.

#include <iostream>
#include <functional>
 
int main()
{
    std::function<int()> f = nullptr;
    try {
        f();
    } catch(const std::bad_function_call& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_alloc

An exception is defined in the header file <new>

Called when the memory can not be allocated.

std::bad_array_new_length

An exception is defined in the header file <new>

An exception is thrown in the following cases:

  1. The array has a negative size
  2. The total size of the new array exceeded the maximum value determined by the implementation
  3. The number of initialization elements exceeds the suggested number of initializers
#include <iostream>
#include <new>
#include <climits>
 
int main()
{
    int negative = -1;
    int small = 1;
    int large = INT_MAX;
    try {
        new int[negative];           // negative size
        new int[small]{1,2,3};       // too many initializers
        new int[large][1000000];     // too large
    } catch(const std::bad_array_new_length &e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_exception

An exception is defined in the header file <exception>

std::bad_exception - This is an exception type in C ++ that is executed in the following situations:

  1. If the dynamic exception specification is violated
  2. If std::exception_ptr stores a copy of the caught exception, and if the copy constructor of the exception object caught the current_exception, then an exception is thrown for exceptions.
#include <iostream>
#include <exception>
#include <stdexcept>
 
void my_unexp() { throw; }
 
void test() throw(std::bad_exception)
{
    throw std::runtime_error("test");
}
 
int main()
{
    std::set_unexpected(my_unexp);
    try {
         test();
    } catch(const std::bad_exception& e)
    {
        std::cerr << "Caught " << e.what() << '\n';
    }
}
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate
P
  • #
  • Oct. 15, 2017, 10 p.m.

std::underflow_error - это не "число имеет слишком большое отрицательное значение", а потеря точности при вычислениях, т.е. результат настолько мал, что не может быть представлен числом в формате IEEE754

Спасибо. Дополнил.

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Looking for a Job?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

JuA
Sept. 17, 2019, 7:51 a.m.
Julija Aleksandrova

C++ - Test 001. The first program and data types

  • Result:33points,
  • Rating points-10
JuA
Sept. 17, 2019, 7:36 a.m.
Julija Aleksandrova

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:10points,
  • Rating points-10
VD
Sept. 16, 2019, 10:47 a.m.
Viktor Dzen'kiv

C++ - Test 002. Constants

  • Result:75points,
  • Rating points2
Last comments
Sept. 17, 2019, 5:07 a.m.
Misha Lebedev

Кстати интересные темы нашёл тут https://emacsway.github.io/ru/django-framework/#django-models Может что полезного тоже Евгений найдёте
Sept. 17, 2019, 3:50 a.m.
Misha Lebedev

Доброго времени суток. Спасибо за хороший ответ, У меня ситуация така что в галлереи будет несколько миллионов фотографий с фильтрами и тегами , и я опасаюсь за производительност . Это ос…
Sept. 17, 2019, 2:23 a.m.
Evgenij Legotskoj

Добрый день. Да, я тоже читал ту статью в своё время и согласен с тем, что внешние ключи гораздо лучше, чем GenericForeignKey. Выборки в ряде случае работают быстрее. Но лично мне про…
Sept. 14, 2019, 4:08 p.m.
Misha Lebedev

Приветствую вас Евгений , давно наблюда за развитием вашего замечательного портала, много полезно тут нашел , переодически зачитываюсь. Теперь по сушеству, делаю портал и там идеально ложи…
Sept. 10, 2019, 3:38 p.m.
Evgenij Legotskoj

function view для модели Article и LikeDislike.LIKE будет выглядеть так def like(request, pk): obj = Article.objects.get(pk=pk) try: likedislike = LikeDislike.objects.get(cont…
Now discuss on the forum
p
Sept. 17, 2019, 4:02 a.m.
pstMem

Да, действительно нужно дебажить, по другому не словить исключение. Уже решил проблему, был выход за предел массива, не правильные входные данные, так что всегда проверяйте размер массива.
Sept. 17, 2019, 2:39 a.m.
Evgenij Legotskoj

Добрый день! На удалённом сервере вряд ли. Этот класс из core модуля, а удалённый сервер - это ещё и network модуль нужно подтягивать. Тут на удалэнном сервере нужно делать программу…
Sept. 17, 2019, 2:30 a.m.
Evgenij Legotskoj

Добрый день! Попробуйте toHex() А также создние QString с помощью from методов. Может быть QString::fromLatin1(). В документации на QString почти два десятка методов from, один из них…
m
Sept. 16, 2019, 12:54 p.m.
mihamuz

Однозначно PostgreSql не ниже 10 ки.
R
Sept. 16, 2019, 6:09 a.m.
RED_Spider

прочитайте https://doc.qt.io/archives/qt-5.11/osx-deployment.html QMAKE_POST_LINK += "~/Qt/5.12.0/clang_64/bin/macdeployqt $${TARGET}.app $$escape_expand( \\n\\t )"
EVILEG
About
Services
© EVILEG 2015-2019
Recommend hosting TIMEWEB