Аскетичная разработка
браузера
Константин Крамлих
Исключения
Исключения. Минусы
▌ Ревью кода после каждого throw
▌ Всегда нужно знать и помнить о гарантиях исключений
▌ Увеличение количества неявных точек выхода из функций
5
Исключения и скорость
int DoSomeJob() {
int result = rand() % 2;
if (result == 0) throw std::exception();
return result;
}
int main() {
int result = 0;
srand(123);
for (int i = 0; i < 1E7; ++i)
try { result += DoSomeJob();}
catch (const std::exception& e){}
std::cout << result << std::endl;
return 0;
}
Исключения и скорость
bool DoSomeJob(int* result) {
int value = rand() % 2;
if (value == 0) return false;
*result = value;
return true;
}
int main() {
int result = 0;
srand(123);
for (int i = 0; i < 1E7; ++i) {
int value = 0;
if (DoSomeJob(&value)) result += value;
}
std::cout << result << std::endl;
return 0;
}
Исключения и скорость
$ time with_exceptions
5000075
real 0m10.063s
user 0m0.000s
sys 0m0.015s
8
$ time without_exceptions
5000075
real 0m0.325s
user 0m0.015s
sys 0m0.000s
Как устроены исключения
▌ Run-time
▌ Compile-time
9
Run-time
try {
f(1);
Foo X;
g(2);
} catch (…) {
// …
}
int g(int) {
Bar y;
throw 1;
}
10
env
env
local objects
local objects
Compile-time
try {
f(1);
Foo X;
g(2);
} catch (…) {
// …
}
11
Go to handler A
Delete X
Go to handler A
Handler A
Как устроены исключения
> nm with_exceptions | c++filt | head -3
0000000100000ed0 short GCC_except_table1
U __Unwind_Resume
0000000100000c50 T DoSomeJob()
12
Исключения. Минусы
▌ Исключение нарушают правило «Ты платишь только за то,
чем пользуешься»
▌ Исключения увеличивают размер приложений
13
Исключения. Минусы
194
225
0
50
100
150
200
250
Размер исполняемых файлов, Мб
Без исключений С исключениями
Исключения не для слабых духом
String EvaluateSalaryAndReturnName(Employee e) {
if (e.Title() == “CEO” || e.Salary() > 100000) {
cout << e.First() << “ “ << e.Last() << “ is overpaid” <<
endl;
}
return e.First() + “ “ + e.Last();
}
Пример взят из книги «Решение сложных задач на C++» Герба Саттера 15
Исключения не для слабых духом
String EvaluateSalaryAndReturnName(Employee e) {
// 1
if (e.Title() == “CEO” || e.Salary() > 100000) {
// 7
cout << e.First() << “ “ << e.Last() << “ is overpaid” <<
endl; // 7
}
return e.First() + “ “ + e.Last();
// 5
}
Итого: 20
Пример взят из книги «Решение сложных задач на C++» Герба Саттера 16
Исключения и асинхронность
17
Что же делать?
Кадр из т/с «Держись, Чарли», режиссёр Боб Коерр 18
Как крашнуть браузер без смс
▌ DCHECK(condition)
▌ CHECK(condition)
▌ NOTREACHED() = DCHECK(false)
19
DCHECK
void LocalSafeBrowsingDatabaseManager::GetChunks(
GetChunksCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(enabled_);
DCHECK(!callback.is_null());
safe_browsing_task_runner_->PostTask(
FROM_HERE,
base::Bind(&GetAllChunksFromDatabase,
this,
callback));
}
20
CHECK
unsigned int BrowserProcessImpl::AddRefModule() {
DCHECK(CalledOnValidThread());
// CHECK(!IsShuttingDown());
if (IsShuttingDown()) {
// Copy the stacktrace which released the final
// reference onto our stack so it will be available in
// the crash report for inspection.
base::debug::StackTrace callstack =
release_last_reference_callstack;
base::debug::Alias(&callstack);
CHECK(false);
}
did_start_ = true;
module_ref_count_++;
return module_ref_count_;
} 21
Проверка кодов возврата
#if defined(__GNUC__)
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define WARN_UNUSED_RESULT
#endif
22
Проверка кодов возврата
bool ReadBool(bool* result) WARN_UNUSED_RESULT;
bool ReadInt(int* result) WARN_UNUSED_RESULT;
bool ReadLong(long* result) WARN_UNUSED_RESULT;
…
23
Исключения. Минусы
▌ Исключения используют RTTI
24
RTTI
RTTI
194 202
0
50
100
150
200
250
Размер исполняемых файлов, Мб
Без RTTI С RTTI
dynamic_cast
class Derived;
class Base {
public:
virtual Derived* AsDerived() { return nullptr; }
};
class Derived : public Base {
public:
Derived* AsDerived() override { return this; }
};
27
Стрельба по ногам
и все-все-все
Арсенал охотников на ноги
▌ Перегрузки функций, для которых будет неявный выбор
перегрузки
▌ Перегрузки операторов
▌ Литералы, определенные пользователем
▌ Дефолтные аргументы
▌ Неконстантные ссылки
▌ Rvalue references
29
Арсенал охотников на ноги
▌ Не-POD глобальные/статические объекты
▌ Friend без веской причины
▌ Нелокальные auto переменные
▌ Возврат и хранение lambda-объектов
▌ Захват всего scope для lambda
▌ Не-explicit конструкторы с одним параметром
30
RValue references
template <class T>
class Foo {
public:
template <class ID>
Foo (Bar&, const ID&) {std::cout << '1';}
template <class ID>
Foo(Bar&, ID&&) {std::cout << '2';}
};
int main() {
Bar b1, b2;
Foo<Bar> f(b1, b2);
}
31
Полезные ссылки
▌ http://www.boost.org/community/error_handling.html
▌ http://programmers.stackexchange.com/questions/113479/are-there-any-real-
world-cases-for-c-without-exceptions
▌ http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Exceptions
▌ http://llvm.org/docs/ExceptionHandling.html
▌ http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf
▌ https://www.usenix.org/legacy/publications/library/proceedings/osdi2000/wiess200
0/full_papers/dinechin/dinechin_html/index.html
32
Полезные ссылки
▌ Константин Крамлих
▌ Разработчик Яндекс.Браузера
▌ kostya-k@yandex-team.ru
33
Контакты
kostya-k@yandex-team.ru
+7-923-188-84-04
Крамлих Константин
Разработчик

Аскетичная разработка браузера