Исключения в C++
От: Шахтер Интернет  
Дата: 23.03.16 14:53
Оценка:
Мне видится, что было бы полезно внести следующие изменения в механизм исключений C++.

Во-первых, добавить новый оператор error.

throw Type(args);

error Type(args);


В отличии от оператора throw, error не прерывает исполнения, а сигнализирует об ошибке.

Блок try/catch должен быть устроен так

try(CatchType obj)
 {
  ....

  error "error 1";

  ....

  throw "error 2";    

  ....
 }


При этом CatchType имеет следующий интерфейс:

class TryCatch
 {
  ....

  public:

   void operator () (const char *str); // для типа const char *

   void operator () (std::exception ex); // для типа std::exception

   ....

   void operator () (); // для оставшихся типов
 };


Т.е. блок try конструирует объект-ловушку и для обработки исключений вызываются методы этого объекта.
При этом может случится несколько вызовов, если в процессе исполнения тела блока был вызван error.

В процессе свёртки стека деструкторы классов принудительно "останавливают" исключения.
Т.е. если в деструкторе произошло исключение, то управление передаётся не на конец try блока, а на конец деструктора.
Тем самым снимается проблема исключений в деструкторах.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Исключения в C++
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 23.03.16 15:03
Оценка: +4
Здравствуйте, Шахтер, Вы писали:

Ш>Мне видится, что было бы полезно внести следующие изменения в механизм исключений C++.

Ты можешь написать в комитет и предложить это улучшение.
Ш>В отличии от оператора throw, error не прерывает исполнения, а сигнализирует об ошибке.
Вызывай функцию mynamepsace::error и сигнализируй.
Ш>Блок try/catch должен быть устроен так
Я не понял какую проблему ты хочешь решать? Откуда повились эти мысли о error? Изучил новый язык?
Sic luceat lux!
Re[2]: Исключения в C++
От: Шахтер Интернет  
Дата: 23.03.16 20:36
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Здравствуйте, Шахтер, Вы писали:


K>Я не понял какую проблему ты хочешь решать? Откуда повились эти мысли о error? Изучил новый язык?


В С++ есть проблема обработки кратных ошибок, возникающая при раскрутки стека.
Вот для её удобного решения с поддержкой языка и нужны изменения в механизме исключений.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Исключения в C++
От: Erop Россия  
Дата: 23.03.16 20:37
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Мне видится, что было бы полезно внести следующие изменения в механизм исключений C++.

1) Зачем запутывать то, что и так запутанно по самое не хочу, ещё дальше?
2) Зачем в деструкторах нужны исключения?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Исключения в C++
От: Шахтер Интернет  
Дата: 24.03.16 01:06
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>Мне видится, что было бы полезно внести следующие изменения в механизм исключений C++.

E>1) Зачем запутывать то, что и так запутанно по самое не хочу, ещё дальше?

Не запутывать, а совершенствовать.

E>2) Зачем в деструкторах нужны исключения?


Класс File, например. Исключение сигнализируют об ошибке. Есть масса естественных ситуаций, когда ошибки возникают при завершающих действиях.

class File : NoCopy
 {
   FileHandle handle;

  private:

   static ErrorType Open(FileHandle &handle,const char *name);

   static ErrorType Close(FileHandle handle);

  public:

   explicit File(const char *name)
    {
     if( ErrorType e=Open(handle,name) ) throw e;
    }

   ~File() noexcept(false)
    {
     if( ErrorType e=Close(handle) ) throw e;
    }
 };

struct CatchType
 {
  void operator() (ErrorType e)
   {
    // печатаем сообщение об ошибке, например
   }
 };

....

try( CatchType catch_obj )
 {
  File file1("name1");
  File file2("name2");

  ....
 
 }

// Дошли до конца блока, сработал деструктор file2, выбросил исключение. При этом был вызван оператор () у catch.
// Дальше пошла раскрутка стека. Сработал деструктор file1. Тоже выбросил исключение. Опять был вызван оператор () у catch. 
// Второе исключение, однако, передало управление на конец деструктора. Т.е. раскрутка стека продолжилась. В конце концов, управление передано на конец try блока.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 04:45
Оценка:
Здравствуйте, Шахтер, Вы писали:


Ш>Класс File, например. Исключение сигнализируют об ошибке. Есть масса естественных ситуаций, когда ошибки возникают при завершающих действиях.


Проблема не в том, что ошибки возникают, а в том, что не понятно как их обрабатывать. Отменить-то деструктор мы обычно не можем?

Вот представь себе, что твой File в качестве трёх полей агрегирован в какой-то класс. Мы разрушаем экземпляр этого класса, и во время разрушения второго File получаем исключение "диск полный". Тут, по идее, пользователю надо дать шанс почистить диск и повторить запись. Как делаем?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Исключения в C++
От: Evgeny.Panasyuk Россия  
Дата: 24.03.16 05:09
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>В процессе свёртки стека деструкторы классов принудительно "останавливают" исключения.

Ш>Т.е. если в деструкторе произошло исключение, то управление передаётся не на конец try блока, а на конец деструктора.
Ш>Тем самым снимается проблема исключений в деструкторах.

В качестве эксперимента можно подобное реализовать на базе unwinding_indicator
Автор: Evgeny.Panasyuk
Дата: 01.10.12
.
Re[4]: Исключения в C++
От: Evgeny.Panasyuk Россия  
Дата: 24.03.16 05:25
Оценка:
Здравствуйте, Erop, Вы писали:

E>Вот представь себе, что твой File в качестве трёх полей агрегирован в какой-то класс. Мы разрушаем экземпляр этого класса, и во время разрушения второго File получаем исключение "диск полный". Тут, по идее, пользователю надо дать шанс почистить диск и повторить запись. Как делаем?


Через TLS-стэк обработчиков или например через корутины/потоки.
В принципе вот такой синтаксис реализуется уже сейчас:
{
    // near stack root
    SPECIAL_TRY
    {
        write_file();
    }
    SPECIAL_CATCH(not_enough_space x)
    {
        if(try_to_free_space(x.size()))
            return continue_execution;
        else
            return throw_exception;
    };
}

{
    // deep inside stack
    raise(not_enough_space{size}); // may throw or continue
    // at this point we have enough space
}
Re[5]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 05:37
Оценка: +3
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Через TLS-стэк обработчиков или например через корутины/потоки.

EP>В принципе вот такой синтаксис реализуется уже сейчас:

Ну это же всё дико сложно работает, и отлаживать трудно и тестами покрывать...

И всё ради чего?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 05:39
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>В С++ есть проблема обработки кратных ошибок, возникающая при раскрутки стека.

Ш>Вот для её удобного решения с поддержкой языка и нужны изменения в механизме исключений.

Это, как минимум, нетестируемо... Тебе надо будет покрывать тестами не только все ошибки, но и все их сочетания...
Или ты надеешься обрабатывать ошибки без сайд-эффектов?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 05:41
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>В качестве эксперимента можно подобное реализовать на базе unwinding_indicator
Автор: Evgeny.Panasyuk
Дата: 01.10.12
.


Проблема не том, как реализовать, а в том, что реализовывать, что бы было не хуже, чем сейчас, а лучше...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Исключения в C++
От: _niko_ Россия  
Дата: 24.03.16 06:32
Оценка: -1
Здравствуйте, Шахтер, Вы писали:

Ш>Класс File, например. Исключение сигнализируют об ошибке. Есть масса естественных ситуаций, когда ошибки возникают при завершающих действиях.


Если:
— при закрытии файла (file.close();) можно словить исключение;
— объект file может быть разрушен при раскрутке стука по исключению
... то сделай так чтобы файл не закрывался при разрушении объекта file — все, проблема решина, т.е. вызов file.close(); в деструкторе file по факту ничего уже закрывать не будет и ошибок не произойдет.

Считаем что закрытие файла при разрушении объекта file (раз в этом случае может сгенирироваться исключение) уже есть не совсем нормальное поведение. И если тут происходит еще что то не нормальное ну значит так таму и быть вылетом из приложения по terminate — все логично.

Изночально нужно писать код так чтобы всегда была альтернатива пробрасыванию исключения из деструктора.
А для перекрытия одного исключения другим как раз таки с C++11 у нас появились вложенные исключения.
Re[2]: Исключения в C++
От: enji  
Дата: 24.03.16 06:41
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Я не понял какую проблему ты хочешь решать? Откуда повились эти мысли о error? Изучил новый язык?


У меня периодически бывают случаи, когда в разных функциях есть одинаковые блоки catch. И счас эта задача нормально не решается — или макры или запоминание и перевыброс текущего исключения (что по идее не быстро)
Re[6]: Исключения в C++
От: Evgeny.Panasyuk Россия  
Дата: 24.03.16 07:10
Оценка:
Здравствуйте, Erop, Вы писали:

EP>>Через TLS-стэк обработчиков или например через корутины/потоки.

EP>>В принципе вот такой синтаксис реализуется уже сейчас:
E>Ну это же всё дико сложно работает, и отлаживать трудно и тестами покрывать...

Не трудно Есть наборы тестовых состояний среды, и ожидаемые отклики, это всё загоняется в наборы тестовых векторов, и соответственно прогоняется. От метода реализации кстати не особо зависит.

E>И всё ради чего?


Ты же задачу такую поставил, или нет? То есть нужно обработать и исправить ошибку где-то выше по логическому стэку компонентов, там где есть необходимая информация и полномочия, а потом продолжить на исходном низком уровне, так?
Сложность-то она в самой задаче, а не в решении.
Re[3]: Исключения в C++
От: Шахтер Интернет  
Дата: 24.03.16 10:14
Оценка:
Здравствуйте, enji, Вы писали:

E>Здравствуйте, Kernan, Вы писали:


K>>Я не понял какую проблему ты хочешь решать? Откуда повились эти мысли о error? Изучил новый язык?


E>У меня периодически бывают случаи, когда в разных функциях есть одинаковые блоки catch. И счас эта задача нормально не решается — или макры или запоминание и перевыброс текущего исключения (что по идее не быстро)


Да, и эта проблема тоже решается.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Исключения в C++
От: Шахтер Интернет  
Дата: 24.03.16 10:18
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Шахтер, Вы писали:


Ш>>В процессе свёртки стека деструкторы классов принудительно "останавливают" исключения.

Ш>>Т.е. если в деструкторе произошло исключение, то управление передаётся не на конец try блока, а на конец деструктора.
Ш>>Тем самым снимается проблема исключений в деструкторах.

EP>В качестве эксперимента можно подобное реализовать на базе unwinding_indicator
Автор: Evgeny.Panasyuk
Дата: 01.10.12
.


Можно, да. Но требует дисциплины программирования. Хочется нормальную поддержку на уровне языка.
И код станет красивше...
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Исключения в C++
От: Шахтер Интернет  
Дата: 24.03.16 10:23
Оценка: -1
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:



Ш>>Класс File, например. Исключение сигнализируют об ошибке. Есть масса естественных ситуаций, когда ошибки возникают при завершающих действиях.


E>Проблема не в том, что ошибки возникают, а в том, что не понятно как их обрабатывать. Отменить-то деструктор мы обычно не можем?


E>Вот представь себе, что твой File в качестве трёх полей агрегирован в какой-то класс. Мы разрушаем экземпляр этого класса, и во время разрушения второго File получаем исключение "диск полный". Тут, по идее, пользователю надо дать шанс почистить диск и повторить запись. Как делаем?


Нет, исключения остаются без возобновления.
А твой случай нужно разруливать не на исключениях, а на продолжениях.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 10:47
Оценка: +3
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Ты же задачу такую поставил, или нет? То есть нужно обработать и исправить ошибку где-то выше по логическому стэку компонентов, там где есть необходимая информация и полномочия, а потом продолжить на исходном низком уровне, так?

EP>Сложность-то она в самой задаче, а не в решении.

Ну вот смотри, мы пишем ТРИ файла, флушим, получаем "места нет", и решаем, то надо спросить пользователя что делать. Пользователь говорит: "пиши док на другой диск". И как это случится?

А альтернативный вариант -- у нас всё пишется явно, а не в деструкторе, и вызывающий код всем рулит, пока оно ещё не разрушилось... Второе очевидно проще же?

А как спрашивать вышестоящий код, что делать, через исключения или через колбэки -- не суть.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 11:01
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>А твой случай нужно разруливать не на исключениях, а на продолжениях.


Вот я и спрашиваю, зачем всё так усложнять?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Исключения в C++
От: smeeld  
Дата: 24.03.16 11:19
Оценка:
Здравствуйте, Шахтер, Вы писали:


Ш>Во-первых, добавить новый оператор error.


Вообще говоря, если исключения в С++ такие, какие они есть, то значит это кому-то нужно. Не нужно пытаться что-то изменить, всё равно проигнорируют. Например, в Lisp-ах исключения более функциональны и более оптимально реализованы, это появилось задолго до появления С++, и в С++ запросто могли взять исключения по образу и подобию Lisp-овых, но вместо этого нагородили что-то явно более уродливое, непродуманное и неоптимальное. Значит это кому-то нужно.
Re: Исключения в C++
От: Mr.Delphist  
Дата: 24.03.16 12:18
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

Ш>В отличии от оператора throw, error не прерывает исполнения, а сигнализирует об ошибке.

Логгер, своя функция и т.п. — сигнализируй не хочу.

Ш>Блок try/catch должен быть устроен так


Опять же, это решается перехватом исключения с подавлением или без подавления этого исключения. Если можем сами — отреагировали на ситуацию и подавили. Если не можем — реагируем на исключение и пробрасываем наверх либо само исключение, либо производное от него (например, оригинальное исключение кладём как дочернее поле в охватывающее исключение, оговоренное контрактом API).
Re[3]: Исключения в C++
От: Шахтер Интернет  
Дата: 24.03.16 13:54
Оценка:
Здравствуйте, enji, Вы писали:

E>Здравствуйте, Kernan, Вы писали:


K>>Я не понял какую проблему ты хочешь решать? Откуда повились эти мысли о error? Изучил новый язык?


E>У меня периодически бывают случаи, когда в разных функциях есть одинаковые блоки catch. И счас эта задача нормально не решается — или макры или запоминание и перевыброс текущего исключения (что по идее не быстро)


Можно делать вот так. Но тут тоже rethrow.

/* main.cpp */ 

#include <iostream>

using namespace std;

/* handle() */

void handle()
 {
  try
    {
     throw;
    }
  catch(int a)
    {
     cout << a << endl ;
    }
  catch(const char *str)
    {
     cout << str << endl ;
    }
 }

/* main() */

int main()
 {
  try
    {
//     throw 12345;
     throw "67890";
    } 
  catch(...)
    {
     handle(); 
    }

  return 0;
 }
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[6]: Исключения в C++
От: _hum_ Беларусь  
Дата: 24.03.16 16:27
Оценка: +1 :)
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>А твой случай нужно разруливать не на исключениях, а на продолжениях.


E>Вот я и спрашиваю, зачем всё так усложнять?


это наверное частный случай более общего вопроса — зачем вообще понадобилось вводить исключения.
Re[7]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 16:38
Оценка: 1 (1)
Здравствуйте, _hum_, Вы писали:

__>это наверное частный случай более общего вопроса — зачем вообще понадобилось вводить исключения.

В данном случае вопрос скорее, зачем вводить продолжения

По исключениям вроде есть удачные практики использования, и там в деструкторах не кидают...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Исключения в C++
От: antropolog  
Дата: 24.03.16 17:18
Оценка:
Здравствуйте, Шахтер, Вы писали:

Кстати, если добавить немного ада в виде оператора запятая, то будет местами похоже на то что тебе нужно, т.е. а-ля:

class catch_dispatcher {
public:
  template <typename T>
  void operator,(const T& obj) const {
    try{
     throw obj;
    }
    catch(...) {
      handle();
    }
  }

  void handle() const {
    try {
      throw;
    }
    catch(int a) {
      cout << "Error: " << a << endl;
    }
    catch(const char* str) {
      cout << "Error: " << str << endl;
    }
    catch(const std::exception& e) {
      cout << "Error: " << e.what() << endl;
    }
  }
};


А затем совсем наркомания:

#define throw_error catch_dispatcher(),

auto main(int argc, char argv[]) -> int try {
  throw_error 42;
  throw_error "Hello!";
  throw_error std::runtime_error("wow");
  throw_error std::string("Bad");
}
catch(...) {
  cout << "Unhandled exception" << endl;
}


Output:

Error: 42
Error: Hello!
Error: wow
Unhandled exception


для сильных духом мужчин:
s/throw_error/throw/g
Re[3]: Исключения в C++
От: Erop Россия  
Дата: 24.03.16 21:07
Оценка:
Здравствуйте, enji, Вы писали:

E>У меня периодически бывают случаи, когда в разных функциях есть одинаковые блоки catch. И счас эта задача нормально не решается — или макры или запоминание и перевыброс текущего исключения (что по идее не быстро)


А почему перевыброс не быстро?
Что там медленного?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Исключения в C++
От: kov_serg Россия  
Дата: 24.03.16 22:38
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

Ш>Мне видится, что было бы полезно внести следующие изменения в механизм исключений C++.


Незнаю как вам. А мне не хватает функции замера и ограничения ресурсов.
Например вызвать метод c ограниченным временем исполнения,
ограничением на использования стека и динамической памяти.
И чтоб при завершении потока автоматом останавливались его дочерние потоки
и освободдались ресурсы которые они выделяли.
И чтоб это было из коробки.

И много еще чего нехватает. Более того некоторые вещи досих пор удивляют и вызывают недоумение.
Проблемма языков высокого уровня, в моём понимании это упростить написание программ, а не наоборот.
И еще как правило надо не просто решить задачу, а с учетоим каких-то ограничений.

наприер задача отсортировать милиард строк при ограничении по доп. памяти в 16Кб.
или в данном файле запрещено использовать шаблоны
или не использовать макросы
или ни каких fpu только хардкор и битовые операции
или другие соглашения, что б их проверял компилятор.

Но C++ не для этого. Он для вечного изучения и поддержания уже написанных костылей

Главная проблемма что на этих языках пишут люди. У всех людей мозг имеет особенности которые мы получили в результате эволюции
их никто не учитывает при написании языков программирования. В отличии от компьютеров
мозг имеет очень ограниченные возможности и имеет известные недостатки. Пока главным инструментом являлась письменность.
Короче: "Без карандаша с блокнотом, настоящего программиста не получится". Именно из-за особенностей мозга.
https://www.youtube.com/watch?v=D_pwT1L7NLU
https://www.youtube.com/watch?v=2PD383EtpRw
Re[8]: Исключения в C++
От: Evgeny.Panasyuk Россия  
Дата: 25.03.16 02:06
Оценка:
Здравствуйте, Erop, Вы писали:

EP>>Ты же задачу такую поставил, или нет? То есть нужно обработать и исправить ошибку где-то выше по логическому стэку компонентов, там где есть необходимая информация и полномочия, а потом продолжить на исходном низком уровне, так?

EP>>Сложность-то она в самой задаче, а не в решении.
E>Ну вот смотри, мы пишем ТРИ файла, флушим, получаем "места нет", и решаем, то надо спросить пользователя что делать. Пользователь говорит: "пиши док на другой диск". И как это случится?
E>А альтернативный вариант -- у нас всё пишется явно, а не в деструкторе, и вызывающий код всем рулит, пока оно ещё не разрушилось... Второе очевидно проще же?

А какая разница — в деструкторе инициируется вопрос пользователю или не в деструкторе Тебе и там и там нужно передать управление в другой контекст, туда где знают как реагировать (например знают как нарисовать GUI диалог), и это основная сложность
Re[9]: Исключения в C++
От: Erop Россия  
Дата: 25.03.16 08:23
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>А какая разница — в деструкторе инициируется вопрос пользователю или не в деструкторе



1) Деструктор трудно отменить.
2) Если в запросе участвует несколько сущностей, то к моменту вызова деструктора одной из них, остальные могут быть уже разрушены.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Исключения в C++
От: _hum_ Беларусь  
Дата: 25.03.16 10:39
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>>А какая разница — в деструкторе инициируется вопрос пользователю или не в деструкторе


E>1) Деструктор трудно отменить.


если речь о с++, то там, вроде бы, еще и проблема в том, что

wiki/Обработка исключений
[...]встречается возможность гарантированного завершения блока кода (finally, ensure). Заметным исключением является Си++, где такой конструкции нет. Вместо неё используется автоматический вызов деструкторов объектов.
[...]
Корректная реализация исключений может быть затруднительной в языках с автоматическим вызовом деструкторов. При возникновении исключения в блоке необходимо автоматически вызвать деструкторы объектов, созданных в данном блоке, но только тех, которые не были ещё удалены обычным порядком. Кроме того, требование прерывания текущей операции при возникновении исключения вступает в противоречие с требованием обязательного автоматического удаления в языках с автодеструкторами: если исключение возникнет в деструкторе, то либо компилятор будет вынужден удалить не полностью освобождённый объект, либо объект останется существующим, то есть возникнет утечка памяти. Вследствие этого генерация неперехватываемых исключений в деструкторах в ряде случаев просто запрещается.

Re[2]: Исключения в C++
От: _hum_ Беларусь  
Дата: 25.03.16 10:48
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Шахтер, Вы писали:


Ш>>Мне видится, что было бы полезно внести следующие изменения в механизм исключений C++.


_>Незнаю как вам. А мне не хватает функции замера и ограничения ресурсов.


полагаете, что все-таки рост объема обрабатываемых данных опередит рост производительности и емкости устройств?
просто это как бы возврат к уровню си — когда приходится значительное внимание уделять особенностям строения машины, на которой предполагается работа алгоритма...




глянул ваши ссылки на ютьюбе. странный там товарищ, попахивающий "лысенковщиной".
Re[10]: Исключения в C++
От: Evgeny.Panasyuk Россия  
Дата: 25.03.16 14:18
Оценка:
Здравствуйте, Erop, Вы писали:

EP>>А какая разница — в деструкторе инициируется вопрос пользователю или не в деструкторе

E>1) Деструктор трудно отменить.

Зачем тебе его отменять?

E>2) Если в запросе участвует несколько сущностей, то к моменту вызова деструктора одной из них, остальные могут быть уже разрушены.


Ты о чём вообще?

У тебя был код:
if(file_flush() == not_enough_space)
     fail();
Стал:
if(file_flush() == not_enough_space)
    if(call_not_enough_space_handler() == successfully_freed_space)
        file_flush();
    else
        fail();

Изменение только в том, что fail будет происходить реже. А вот где он был, и какой механизм использовался — это ортогонально данной дополнительной обработке
Re[11]: Исключения в C++
От: Erop Россия  
Дата: 25.03.16 16:00
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Зачем тебе его отменять?

Ну вот смотри, сценарий.
Я, такой красивый, нажал кнопочку "закрыть окно", окно закрывается, документ флушится на диск, и тут бабам! "МЕСТО ЗАКОНЧИЛОСЬ, ПРИМИТЕ МЕР!".
Я такой смотрю и понимаю, что уронил нечаянно голову на Ctrl+V и так поспал полчасика, и надо бы файло поредактировать мальца, перед тем, как окончательно записывать...
Ну я такой, в филесаве диалоге говорю "отменить", и? Что дальше происходит?

EP>У тебя был код:

EP>
EP>if(file_flush() == not_enough_space)
EP>     fail();
EP>
Стал:

EP>
EP>if(file_flush() == not_enough_space)
EP>    if(call_not_enough_space_handler() == successfully_freed_space)
EP>        file_flush();
EP>    else
EP>        fail();
EP>

EP>Изменение только в том, что fail будет происходить реже. А вот где он был, и какой механизм использовался — это ортогонально данной дополнительной обработке

А если хендлеру надо ПЕРЕМЕСТИТЬ этот файл на другой диск, тока в комплекте ещё с двумя другими. Но CFile одного из этих других уже разрушен?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Исключения в C++
От: ononim  
Дата: 26.03.16 13:36
Оценка: +1
немного не по теме но иногда хотелось бы чтобы можно было написать вместо try — retry
то есть бывает некая последовательность действий, которую можно выполнить несколько раз, но в ходе выполнения которой могли бы быть некие проблемы, которые можно починить в catch и перезапустить исходную последовательность
типа
void inner()
{
 some_vector.resize(some_value);
}

void outer()
{
 try
 {
  inner();
 }catch (bad_alloc &a)
 {
  free_some_memory();
  inner();//если исключение вылезет и отсюда - значицца у нас ничего не получилось :(
 }
}

можно было бы заменить на эквивалентное

void outer()
{
 retry 
 {
  some_vector.resize(some_value);
 }catch (bad_alloc &a)
 {
  free_some_memory();
 }
}

или как вариант параметризовать try количеством пере-попыток (по дефолту значицца оно равно нулю):
void outer()
{
 try(1)
 {
  some_vector.resize(some_value);
 }catch (bad_alloc &a)
 {
  free_some_memory();
 }
}
Как много веселых ребят, и все делают велосипед...
Отредактировано 26.03.2016 13:40 ononim . Предыдущая версия .
Re[2]: Исключения в C++
От: kov_serg Россия  
Дата: 26.03.16 17:16
Оценка:
Здравствуйте, ononim, Вы писали:

O>немного не по теме но иногда хотелось бы чтобы можно было написать вместо try — retry

O>то есть бывает некая последовательность действий, которую можно выполнить несколько раз, но в ходе выполнения которой могли бы быть некие проблемы, которые можно починить в catch и перезапустить исходную последовательность

Что мешает сделать примерно так?
...
struct Try { 
    int en,cnt;
    Try() { en=1; cnt=0; }
    operator int() { return en; }
    void handle() { 
        cnt++;
        try {
            throw;
        } catch(EMemory *e) {
            if (cnt==1) gc();
            if (cnt==2) { en=0; throw; }
            //...
        } catch(...) {
            en=0;
            throw;
        }
    }    
    void gc() { /*...*/ }
};

#define TRY for(Try t;t;) { try {
#define END } catch(...) { t.handle(); } }

...

TRY some_work(); END
Re[3]: Исключения в C++
От: ononim  
Дата: 26.03.16 18:00
Оценка:
моя задумка чтоб код получился попроще для написания и чтения, причем для разных вариантов кода в catch и разных исключений. Вариант с памятью — просто вариант. Могут быть куча других ситуаций типа:
 try(5)
 {
  host.resolve();
  host.connect();
 }catch (network_error &a)
 {
  sleep(1);
 }

или
 try(1)
 {
  read_config();
 }catch (config_broken &a)
 {
  restore_from_backup();
 }

И для каждого случая рисовать свою структуру? Тогда уж проще по старинке...
Как много веселых ребят, и все делают велосипед...
Отредактировано 26.03.2016 18:04 ononim . Предыдущая версия .
Re[4]: Исключения в C++
От: kov_serg Россия  
Дата: 26.03.16 18:42
Оценка:
Здравствуйте, ononim, Вы писали:

O>моя задумка чтоб код получился попроще для написания и чтения, причем для разных вариантов кода в catch и разных исключений. Вариант с памятью — просто вариант. Могут быть куча других ситуаций типа:


И что мешает. Это тоже прото эскиз:
struct Policy {
    static Policy* getContextPolicy();
    virtual void handle(int limit) {
        try {
            throw;
        } catch(EMemory *) {
            //...
        } catch(...) {
            //...
        }
    }
};

struct Try { 
    int limit;
    Policy *policy;
    Try(int count,Policy *policy) { limit=count; }
    operator int() { return limit>0; }
    void handle() { 
        if (limit-->0) policy->handle(limit);
        else throw;
    }    
    void gc() { /*...*/ }
};

#define TRY_LIMIT(n) for(Try t(n,Policy::getContextPolicy());t;) { try {
#define END } catch(...) { t.handle(); } }

...
TRY_LIMIT(3) some_work(); END


O>И для каждого случая рисовать свою структуру? Тогда уж проще по старинке...

Зачем. Как обрабатывать отказы должен задавать вызывающий. И вообще включи воображение. Вариантов тьма.
Re[5]: Исключения в C++
От: ononim  
Дата: 26.03.16 19:02
Оценка:
O>>И для каждого случая рисовать свою структуру? Тогда уж проще по старинке...
_>Зачем. Как обрабатывать отказы должен задавать вызывающий. И вообще включи воображение. Вариантов тьма.
Вариантов тьма. А вот варинтов таких, чтобы нуб придя на проект в течении секунд 20 врубился что делает код сейчас ровно один:
try
{
work();
}catch
{
repair();
work();
}

Ваши примеры к таким не относятся. Кроме того последний вариант требует "заточки" под себя кода, который он обслуживает, что опять же ухудшает понимабельность и рефакторабельность кода.
Как много веселых ребят, и все делают велосипед...
Re[6]: Исключения в C++
От: kov_serg Россия  
Дата: 26.03.16 19:52
Оценка:
Здравствуйте, ononim, Вы писали:

O>>>И для каждого случая рисовать свою структуру? Тогда уж проще по старинке...

_>>Зачем. Как обрабатывать отказы должен задавать вызывающий. И вообще включи воображение. Вариантов тьма.
O>Вариантов тьма. А вот варинтов таких, чтобы нуб придя на проект в течении секунд 20 врубился что делает код сейчас ровно один:
O>
O>try
O>{
O>work();
O>}catch
O>{
O>repair();
O>work();
O>}
O>

O>Ваши примеры к таким не относятся. Кроме того последний вариант требует "заточки" под себя кода, который он обслуживает, что опять же ухудшает понимабельность и рефакторабельность кода.

Нет проблем. Только кому это надо?
struct ECritical {};
struct EIgnorable {};

struct Try {
    int stage,limit; 
    enum { Recover=0,Body=1,Success=2,Leave=3 };
    Try(int count) { stage=1;limit=count-1; }
    operator int() { return stage!=3; }
    void step() { if (stage==0) stage=1; stage++; }
    void handle() {
        if (stage<=1) {
            check_exception();
            if (limit>0) { limit--; stage=-1; }
            else throw;
        } else {
            throw;
        }        
    }
    void check_exception() {
        try { throw; } 
        catch(ECritical) { throw; }
        catch(EIgnorable) { } 
        catch(...) { /*unexprected*/ throw; }
    }
};

#define TRY_LIMIT(n) try{for(Try t(n);t;t.step()) { try { switch(t.stage) {
#define RECOVER      case 0:
#define BODY         case 1:
#define SUCCESS      break; case 2:
#define FAIL         }} catch(...) { t.handle(); }}} catch(...) {
#define END_REPEAT   }

...

int ok=0;

TRY_LIMIT(3)
RECOVER { gc(); }
BODY    { some_work(); }
SUCCESS { ok=1; }
FAIL    { ok=0; /*throw;*/ }
END_REPEAT
Re[7]: Исключения в C++
От: kov_serg Россия  
Дата: 26.03.16 20:00
Оценка:
даже так можно сделать.
TRY_LIMIT(3) {
RECOVER { gc(); }
BODY    { some_work(); }
SUCCESS { ok=1; }
FAIL    { ok=0; /*throw;*/ }
}
Re[7]: Исключения в C++
От: ononim  
Дата: 26.03.16 22:08
Оценка:
_>Нет проблем. Только кому это надо?

...проще надо быть
#define RETRY(ATTEMPTS) for(int try_attempt = 0; try_attempt <= ATTEMPTS; ++try_attempt) try {
#define CATCH(E) break; } catch(E) {
#define DONE }

int _tmain(int argc, _TCHAR* argv[])
{
    RETRY(3)
    {
        if (--argc) throw std::exception("world");
        printf("done\n");
    }
    CATCH(std::exception &e)
    {
        printf("hello %s\n", e.what());
    }
    DONE
    return 0;
}

или со строгим киданием исключения выше:

#define RETRY(ATTEMPTS) for(int try_attempt = 0, max_attempt = ATTEMPTS; ; ++try_attempt) try {
#define REPAIR(E); break; } catch(E) { if (try_attempt == max_attempt) throw;
#define DONE }

int _tmain(int argc, _TCHAR* argv[])
{
    RETRY(3)
    {
        if (--argc) throw std::exception("world");
        printf("done\n");
    }
    REPAIR(std::exception &e)
    {
        printf("hello %s\n", e.what());
    }
    DONE
    return 0;
}

но все равно это костыль имхо
Как много веселых ребят, и все делают велосипед...
Отредактировано 26.03.2016 22:47 ononim . Предыдущая версия .
Re[3]: Исключения в C++
От: Erop Россия  
Дата: 27.03.16 18:59
Оценка:
Здравствуйте, _hum_, Вы писали:

__>полагаете, что все-таки рост объема обрабатываемых данных опередит рост производительности и емкости устройств?


От области зависит...
Я вот в области AI работаю, например, таки у нас часто можно разменять время, память и прочую производительность на качество результата. Так что постановка задачи "думаем скока можем себе позволить" вполне жизненная.

Например, если т игрока в шахматы с контролем времени пишешь, то тебе полезно знать скока у тебя осталось времени, а если какой-то рекурсивный переборщик, да ещё и в многопоточном окружении работающий, то часто хочется узнать что-то вроде ответа на вопрос "а сколько её стека есть?"
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Исключения в C++
От: Erop Россия  
Дата: 27.03.16 19:02
Оценка:
Здравствуйте, ononim, Вы писали:

O>или как вариант параметризовать try количеством пере-попыток (по дефолту значицца оно равно нулю):

O>
O>void outer()
O>{
O> try(1)
O> {
O>  some_vector.resize(some_value);
O> }catch (bad_alloc &a)
O> {
O>  free_some_memory();
O> }
O>}
O>



Дык, прямо ща можно же
void outer()
{
    re:try {
        some_vector.resize(some_value);
    }catch (bad_alloc &a) {
    if( try_free_some_memory() )
        goto re;
    }
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.