Очистка указателя от исключения - PullRequest
2 голосов
/ 09 июня 2009

Мы все знаем, что бросать указатели на исключения - это плохо:

try
{
    ...
    throw new MyExceptionClass();
}
catch (MyExceptionClass* e)
{
    ...
}

Как вы подходите к очистке уловленных целей в унаследованном коде? Я полагаю, что могу исправить первую часть, сделав operator new приватным:

class MyExceptionClass
{
public:
    ...
private:
    void* operator new(size_t);
}

Как я могу сделать уловку одинаково уродливой во время компиляции? Я не хочу просто заставить это упасть на территорию catch (...).

Ответы [ 5 ]

3 голосов
/ 10 июня 2009

Вы ничего не можете сделать, чтобы предотвратить отлов по указателю, кроме инструментов статического анализа или проверки кода. Однако, если вы сделаете почти невозможным выброс указателя MyExceptionClass, блок catch(MyExceptionClass*) будет мертвым кодом.

Чтобы более полно предотвратить бросок по указателю, вам действительно нужно проделать дополнительную работу.

Скрыть все формы оператора new - Смотри здесь .

Скрыть оператор адреса - Бросание адреса ранее выделенного объекта влечет за собой некоторые из тех же проблем, связанных с бросанием объекта, выделенного в куче.

class MyExceptionClass
{
private:
    MyExceptionClass* operator&();
}
2 голосов
/ 10 июня 2009

Если я вас правильно понимаю, вы хотите превратить плохую практику в ошибку компиляции.

Сделав тип исключения не подлежащим распределению в куче, вам удалось сделать это недопустимым:

throw new MyExceptionClass();

Увы, следующая часть не может быть выполнена так, как вы этого хотите. Нет никакого способа сделать блок улова незаконным. Хотя, если вы сделали незаконным выделение MyExceptionClass для кучи, вам не нужно беспокоиться о блоках catch. Это просто пустое место.

Если вы хотите, чтобы указатель не перехватывался, вам нужен инструмент, похожий на пух. Я бы рекомендовал посмотреть на EDoC ++ . Это модифицированный компилятор gcc для проверки правильности использования исключений.

1 голос
/ 09 июня 2009

Звучит так, будто вы хотите иметь возможность изменять все экземпляры throw по указателю на throw по значению. У вас есть работоспособный кладж для предотвращения броска по указателю. Но вы ищете способ предотвратить случайный отлов указателем после изменения всех бросков.

Насколько я знаю, это не может быть применено языком. Но простой сценарий sed для поиска экземпляров /catch (.* \*/ должен быть достаточно хорошим, я думаю ...

0 голосов
/ 09 июня 2009

Что касается правил языка C ++, вы не можете запретить указатели на тип, который делает их отлов вполне законным (хотя и некрасивым). Я написал бы простой инструмент, который будет искать все блоки catch(T*) и просто менять их.

Я бы сказал, что operator new private может не работать, потому что глобальный новый оператор все еще может быть вызван. То, что я бы предложил для устаревших баз кода для принудительного разрушения динамического выделения, - это изменить сигнатуру конструктора MyExceptionClass - или добавить статическое утверждение в конструктор по умолчанию и принудительно вызвать ошибки компиляции, чтобы вы могли определить эти созданные по умолчанию типы MyExceptionClass создаются.

Еще один подход, который я бы выбрал, - это поиск предложений 'throw new' и просто их исправление.

0 голосов
/ 09 июня 2009

Я обычно

try
{
  throw MyException();
}
catch (const MyException& e)
{
}

Не уверен, однако, я правильно понимаю ваш вопрос.

...