Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Operok
177 / 175 / 66
Регистрация: 15.02.2015
Сообщений: 505
Завершенные тесты: 2
#1

Спецификатор noexcept для класса "исключение"

01.02.2017, 12:45. Просмотров 220. Ответов 8
Метки нет (Все метки)

Доброго все дня!
Стандартный класс std::exception имеет спецификатор noexcept для всех своих методов/операторов/конструкторов. Однако, он работает с копированием строк и, следовательно, с кучей, что либо допускает вероятность std::bad_alloc в конструкторе исключения, либо в случае неудачной аллокации what вернёт некоторое сообщение, размещённое на стеке, вместо переданного в конструктор. Так ли это, поправьте, пожалуйста?
При написании собственного класса исключения, который собирает различную информацию (кто, куда откуда и когда его бросил), стоит ли обезопасить себя от bad_alloc и пользоваться "сишными" функциями-аллокаторами (ну или ловить его, используя те же строки "из коробки"), или не стоит: пускай бросается, там глядишь, кто-нибудь поймает и разберётся (хотя с чем тут разбираться, если bad_alloc)?
Я понимаю, что bad_alloc - это очень критично для программы, и скорее всего нет смысла продолжать её работу, и возникает такая ситуация скорее всего не в случае реальной нехватки памяти, а при попытке получить слишком большой кусок, но как можно определять у функции спецификатор noexcept, если такая вероятность есть?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.02.2017, 12:45
Ответы с готовыми решениями:

Необработанное исключение в "0x778e15de" в "dir-3.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00000000"
#include <windows.h> #include <d3d9.h> LRESULT __stdcall WndProc(HWND hWnd,...

Необработанное исключение в "0x00412b4a" в "kursovik.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00000004".
Программа компилируется нормально но потом на строчке...

Необработанное исключение в "0x013f2b22" в "123.exe": 0xC0000005: Нарушение прав доступа при записи "0xfdfdfdfd"
Вот функция для удаления столбца: #pragma once #include <iostream> using...

Необработанное исключение в "0x00414558" в "467.exe": 0xC0000005: Нарушение прав доступа при чтении "0xabababbb"
При выполнении этого кода #include <iostream> #include<conio.h> using...

Необработанное исключение в "0x775e15de" в "laba3.exe": 0xC0000005: Нарушение прав доступа при чтении "0xfdfdfdf9".
вылезает ошибка Необработанное исключение в "0x775e15de" в "laba3.exe":...

8
hoggy
Нарушитель
Эксперт С++
7054 / 3100 / 643
Регистрация: 15.11.2014
Сообщений: 7,062
Завершенные тесты: 1
01.02.2017, 12:50 #2
Цитата Сообщение от Operok Посмотреть сообщение
Однако, он работает с копированием строк и, следовательно, с кучей, что либо допускает вероятность std::bad_alloc в конструкторе
он не работает ни с какими строками.
вот весь класс:

C++
1
2
3
4
5
6
7
8
class exception {
public:
  exception () noexcept;
  exception (const exception&) noexcept;
  exception& operator= (const exception&) noexcept;
  virtual ~exception();
  virtual const char* what() const noexcept;
}
1
Operok
177 / 175 / 66
Регистрация: 15.02.2015
Сообщений: 505
Завершенные тесты: 2
01.02.2017, 13:17  [ТС] #3
"А слона то я и не приметил". Был уверен, что конструктор: explicit exception(const char*) noexcept; - это часть стандарта.
Однако это не отменяет тот факт, что некоторые компиляторы такой конструктор как-то поддерживают, более того, наследуемый от exception класс invalid_argument имеет таки конструктор(ы) с передаваемой строкой в качестве параметра. Вопросы в силе.
0
Croessmah
++Ͻ
14543 / 8302 / 1560
Регистрация: 27.09.2012
Сообщений: 20,368
Записей в блоге: 3
Завершенные тесты: 1
01.02.2017, 13:31 #4
Цитата Сообщение от Operok Посмотреть сообщение
с передаваемой строкой в качестве параметра.
Если присмотритесь, то он принимает ссылку на объект std::string,
либо же указатель на строку C'шную (помолимся за нее великому нулю),
т.е. сама строка формируется непосредственно в коде пользователя.
Если у пользователя там что-то не получилось - извините.
А как этой строкой распоряжается внутри invalid_argument - неизвестно.
Например, для подобных случаев, возможно,
память уже зарезервирована, а возможно что и нет.
И да, у invalid_argument конструкторы не noexcept, заметьте.
1
MrGluck
Модератор
Эксперт CЭксперт С++
8078 / 4931 / 1431
Регистрация: 29.11.2010
Сообщений: 13,366
01.02.2017, 13:46 #5
Если случился std::bad_alloc, то ничего кроме std::terminate (а именно он вызывается при прокидывании исключения в noexcept методе) и не сделаешь.
Зато noexcept позволяет компилятору оптимизировать код.

Добавлено через 3 минуты
И если посмотреть, то версия с std::string всего-лишь вызывает метод .c_str() и использует перегруженную версию с указателем. Никакого копирования объекта std::string не происходит.
0
Operok
177 / 175 / 66
Регистрация: 15.02.2015
Сообщений: 505
Завершенные тесты: 2
01.02.2017, 13:53  [ТС] #6
Цитата Сообщение от Croessmah Посмотреть сообщение
И да, у invalid_argument конструкторы не noexcept, заметьте.
Да, заметил. Обратил внимание с начала, что в описании возможных исключений их нет и отождествил это с noexcept.
Значит, не определяю методы класса-исключения как noexcept.

Цитата Сообщение от Croessmah Посмотреть сообщение
Если присмотритесь, то он принимает ссылку на объект std::string,
либо же указатель на строку C'шную (помолимся за нее великому нулю),
т.е. сама строка формируется непосредственно в коде пользователя.
Если у пользователя там что-то не получилось - извините.
Так invalid_argument (или logic_error) должен как-то скопировать строку себе (именно сишную строку), мало ли откуда пользователь её получил, может там rvalue какой-нибудь throw logic_error(string("что-то ") + "пошло " + "не так!");, а соответствующего конструктора нету.
0
Renji
2102 / 1543 / 470
Регистрация: 05.06.2014
Сообщений: 4,473
01.02.2017, 15:39 #7
Цитата Сообщение от Operok Посмотреть сообщение
При написании собственного класса исключения, который собирает различную информацию (кто, куда откуда и когда его бросил), стоит ли обезопасить себя от bad_alloc и пользоваться "сишными" функциями-аллокаторами
Нафиг аллокаторы.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyException:public std::exception
{
public:
    MyException(const char*format,...)noexcept
    {
        va_list args;
        va_start(args,format);
        vsnprintf(data,1024,format,args);
        va_end(args);
    }
 
    const char*what()const noexcept{return data;}
 
private:
    char data[1024];//Вам мало килобайта? Нет, серьезно?
};
int main()
{
    try
    {
        throw MyException("%d*%d=%d",2,2,4);
    }
    catch(const std::exception&error)
    {
        std::cout<<error.what()<<std::endl;
    }
    return 0;
}
1
Operok
177 / 175 / 66
Регистрация: 15.02.2015
Сообщений: 505
Завершенные тесты: 2
01.02.2017, 15:56  [ТС] #8
Цитата Сообщение от Renji Посмотреть сообщение
Нафиг аллокаторы.
...
Если в одной функции будет порядка десятка-двух ответвлений с возможным броском этого (или наследуемого) исключения, то такую функцию опасно будет вызывать в другом потоке (стек не резиновый).

Не по теме:

Цитата Сообщение от Renji Посмотреть сообщение
Вам мало килобайта? Нет, серьезно?
Видел, как одно приложение .NET выкидывало необработанное исключение, текст которого с развернутым стеком вызовов мог и не уместиться в 1кБ :D

0
Renji
2102 / 1543 / 470
Регистрация: 05.06.2014
Сообщений: 4,473
01.02.2017, 16:06 #9
Цитата Сообщение от Operok Посмотреть сообщение
Если в одной функции будет порядка десятка-двух ответвлений с возможным броском этого (или наследуемого) исключения, то такую функцию опасно будет вызывать в другом потоке (стек не резиновый).
Стек сейчас порядка нескольких мегабайт. Даже если каждая функция будет класть туда по килобайту, потребуется тысяча вложенных вызовов чтобы стек переполнить. Так что для большинства задач он вполне резиновый.
0
01.02.2017, 16:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.02.2017, 16:06

Необработанное исключение в "0x01082855" в "sort.exe": 0xC0000005: Нарушение прав доступа при записи "0xcccccccc"
Всем привет! помогите мне понять в чём дело. написал программу: #include...

Необработанное исключение в "0x1027c9c7 (msvcr100d.dll)" в "gh.exe": 0xC0000005: Нарушение прав доступа при чтении "0xfeeefeee".
// gh.cpp: определяет точку входа для консольного приложения. // #include...

Ошибка Необработанное исключение в "0x001d18f8" в "lr7v2.exe": 0xC0000005: Нарушение прав доступа при чтении "0xcdcdcde9"
class Hdd { public: char Hdd_name; int total_space; int free_space;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru