Чем отладка отличается от исполняемого файла релиза?
У меня была ошибка программирования, как это в размере malloc:
buffer = (char *) malloc(cbHash + 1);
assert(buffer);
вместо:
buffer = (char *) malloc(cbHash * 2 + 1);
assert(buffer);
Я писал в буфере в два раза больше, но в режиме отладки все работало нормально, но при выпуске он вылетал в assert, вот как я понял свою ошибку. Мой вопрос: как отладка отличается от исполняемого файла релиза? и почему я не получил ошибку в режиме отладки?
3 ответа
Потому что вы писали все еще в памяти приложения. Кроме того, запись вне выделенной памяти приводит к неопределенному поведению, не обязательно к краху. Запись вне памяти приложения приводит к сбою, потому что система видит, что приложение нарушает память другой программы, и выдается ошибка нарушения доступа. Однако, если вы остаетесь в памяти приложения, система ничего не может сказать, и программы переходят в состояние UB.
Это краткое базовое объяснение. Это немного больше. Если вам интересно, я предлагаю изучить адресные пространства и права доступа к памяти.
Кроме того, режим отладки часто не имеет каких-либо оптимизаций и содержит символы отладки в отличие от сборок релиза. Они могут содержать символы, но часто не содержат.
Утверждение может потерпеть неудачу, только если malloc
не удалось по какой-то причине.
Существует три основных способа отладки и выпуска MSVC
- Релиз использует оптимизатор, а отладка - нет
- Отладка включает символическую информацию отладки в объектных файлах, а выпуск не включает
- Библиотеки времени выполнения разные.
Один из способов отличия библиотек времени выполнения состоит в том, как реализован malloc. Отладочный malloc выделяет дополнительную память с обеих сторон вашего объекта и устанавливает дополнительную память в битовый шаблон. Когда вы освобождаете память, если дополнительные биты были изменены, ваша программа имеет ошибку перезаписи памяти, и она сообщит вам об этом.
Кучи отладки выделяет больше памяти, чем запрошено, и дополняет область "NoMansLand" до и после буфера специальной подписью. Это сделано для обнаружения переполнения буфера. Когда память освобождается, отладочная сборка проверяет подписи и печатает ошибку, если она изменилась.
Сам блок памяти также инициализируется специальными значениями для msvcpp 0xcccccccc. В сборке релиза память оставлена как есть и может содержать любые значения. Это делается для того, чтобы попытаться обнаружить ошибки кодирования, которые не могут инициализировать память. Возможно, это может быть причиной запуска отладочной сборки, в то время как сборка релиза дает сбой: если 0x00000000 плохо для программы, это не приводит к сбою при отладочной сборке, но может происходить при сборке выпуска.