Многие программисты очень любят обвинять компилятор в различных ошибках.
Давайте немного поговорим об этом.
Был ли мальчик?
Когда программист говорит, что причиной ошибки является компилятор, в 99% случаев он лжет. Когда начинается детальное изучение проблемы, то, как правило, причины следующие:- выход за границы массива;
- неинициализированная переменная;
- опечатка;
- ошибка синхронизации в параллельной программе;
- использование энергонезависимой переменной, где это необходимо;
- написан код, приводящий к неопределенному поведению;
- и так далее.
Мы много читаем о них.
Однако это не мешает компилятору снова и снова обвинять в смертных грехах.
Каждый раз кажется, что теперь виноват именно он.
Конечно, компилятор также может содержать ошибки.
Но если вы не используете экзотический компилятор для микроконтроллера, то такая вероятность очень мала.
За многие годы работы с Visual C++ я видел только один раз, когда он генерировал неверный ассемблерный код.
Небольшая рекомендация
Прежде чем обвинять компилятор и писать об этом в коде или на форуме, проведите детальное расследование.Во-первых, так вы быстрее исправите ошибку в своем коде.
Во-вторых, вы не будете выглядеть глупо в глазах других программистов, которые укажут на вашу ошибку.
Что побудило меня написать эту заметку
Сегодня меня крайне позабавил кусок кода из проекта ffdshow. А вот и он:Глядя на комментарий, представляю, как возмутился программист. Ох уж этот отвратительный компилятор! В Debug-версии все переменные равны 0. В релизной версии из-за сломанной оптимизации они мусорные.TprintPrefs::TprintPrefs(IffdshowBase *Ideci, const TfontSettings *IfontSettings) { memset(this, 0, sizeof(this)); // This doesn't seem to // help after optimization. dx = dy = 0; isOSD = false; xpos = ypos = 0; align = 0; linespacing = 0; sizeDx = 0; sizeDy = 0; .
}
Этот беспорядок! Плохой, плохой компилятор! Отругав компилятор, программист оставляет обвинительный комментарий.
И он пишет код ниже, который индивидуально сбрасывает каждый член класса.
Победа мужества над силами зла.
И главное, этот человек останется уверенным, что столкнулся с ошибкой в компиляторе.
И он расскажет, как он пострадал из-за него.
Если кто-то не понимает юмора ситуации, то поясню.
Функция memset() не работает из-за простой ошибки.
Третий аргумент вычисляет размер указателя, а не размер структуры.
Правильный вызов должен выглядеть так: «memset(this, 0, sizeof(*this));».
Кстати, у этого программиста функция memcpy() тоже работает плохо.
Я уверен, что он считает разработчиков компиляторов нечестными существами.
void Assign(const AVSValue* src, bool init) {
if (src->IsClip() && src->clip)
src->clip->AddRef();
if (!init && IsClip() && clip)
clip->Release();
// make sure this copies the whole struct!
//((__int32*)this)[0] = ((__int32*)src)[0];
//((__int32*)this)[1] = ((__int32*)src)[1];
memcpy(this,src,sizeof(this));
}
Из комментариев видно, что он пытался скопировать память альтернативными методами.
Однако затем я оставил функцию memcpy().
Возможно, у него это сработало в 64-битной программе.
Там размер указателя составляет 8 байт. А именно 8 байт он хочет скопировать.
Ошибка снова в третьем аргументе.
Должно быть написано «sizeof(*this)».
Так рождаются легенды о глючных компиляторах и отважных программистах, которые с ними борются.
Заключение
Если что-то работает не так, ищите ошибку в своем коде.Теги: #si #si #C++ #C++ #ошибки кода #ошибки программиста #компиляторы #C++ #компиляторы #C++
-
Языковая Механика Профилирования Памяти
19 Oct, 24 -
Ищем Мелодию По Фрагменту
19 Oct, 24 -
Phonegap: Как Сделать Приложение Отзывчивым
19 Oct, 24