arctic-engineers-club

Open full view…

Обработка ошибок

f1af
Fri, 24 Nov 2017 06:39:05 GMT

Хорошим и продуманным интерфейсом - пользоваться правильно легко, и пользоваться не правильно - сложно. Я думаю, что код на С++ потенциально должен быть без ошибок в принципе. Майерс со мной согласен. Интерфейс должен распологать к тому, чтобы при пользовании им ошибок не возникало вообще. Пример кода с потенциальной ошибкой: --------- void foo(const VectorArray *va) { AE_ASSERT(va, "error: null pointer"); ... } ------ Тот же код, потенциально без ошибки: ------ void foo(const VactorArray &va) { ... } ------ Таких примеров в книге Майерса полно. Проверять "const char *messgae" на ноль не стоит. Потому что под строковые литералы память выделается на всё время жизни программы. Например: ------- class A { const char *str; public: A(const char *str) : str(str) {} void work() { std::cout << str; } }; void main() { A a("qwe"); a.work(); } --------- По "qwe" будет выделена память на страрте программы, так что указательно на str всегда будет валиден. Если строки беруться из файла, то сам парсер файла должен позаботиться о том, чтобы строковые указатели, которые он генерирует, не были нулевыми.

f1af
Fri, 24 Nov 2017 06:49:36 GMT

Я нашёл ошибку в коде. ---------- void ByteArray::Resize(Ui64 size) { if (size <= allocated_size_) { size_ = size; } else { Ui8 *data = static_cast<Ui8*>(malloc(static_cast<size_t>(size))); Check(data != nullptr, "Allocaton error."); ... } } void Fatal(const char *message, const char *message_postfix) { size_t size = 1 + strlen(message) + (message_postfix ? strlen(message_postfix) : 0); char *full_message = static_cast<char *>(malloc(size)); memset(full_message, 0, size); snprintf(full_message, size, "%s%s", message, (message_postfix ? message_postfix : "")); std::cerr << "Arctic Engine ERROR: " << full_message << std::endl; exit(1); } -------- Сообщеие "Allocaton error." не будет выведено, потому что malloc в Fatal не сработает (при условии что выделяемая память меньше или равно чем длина сообщения об ошибке). Ошибку можно сиправить так: ------------- void Fatal(const char *message, const char *message_postfix) { const int buf_size = 255; static char full_message[buf_size]; snprintf(full_message, buf_size, "%s%s", message, (message_postfix ? message_postfix : "")); std::cerr << "Arctic Engine ERROR: " << full_message << std::endl; exit(1); } ---------- Но в данном случае лучше будет написать так: ---------- void Fatal(const char *message, const char *message_postfix) { std::cerr << "Arctic Engine ERROR: " << full_message << message_postfix ? message_postfix : "" << std::endl; terminate(); } ---------- Тут я так же занименил exit(1) на terminate(). Так, мы сможет при помощи отладчика увидеть весь трейс, приведший к ошибке.

bladez-fate
Fri, 24 Nov 2017 08:29:13 GMT

*Huldra* неожиданный код вывода ошибки, зачем так сложно? *f1af* Не понял, в каком еще раз случае? если памяти не хватило чтоль? дак это кирдык все равно и у тебя не malloc сломается

Huldra
Fri, 24 Nov 2017 09:04:15 GMT

Код вывода ошибки изначально писался под Windows и выводил текст в окошко, поэтому там так сложно. Под Linux я не нашла стандартного способа показать окошко при ошибке и просто заменила окошко на cerr. Поэтому так сложно. На случай, когда кончается память, надо будет вообще что нибудь ненужное деаллоцировать перед выводом сообщения об ошибке, чтобы точно вывелось. Убрать оттуда аллокацию - отличная идея! Когда я писала сообщение об ошибке выделения памяти, основной мыслью было, что память выделяется под спрайт или звук, и это может быть сотня мегабайт. И вот 100 мегабайт запросто может не выделиться из-за фрагментации, например. При этом сообщение об ошибке все равно вывелось бы. Но, конечно, надо сделать нормально.