Чем отладка отличается от исполняемого файла релиза?

У меня была ошибка программирования, как это в размере 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 плохо для программы, это не приводит к сбою при отладочной сборке, но может происходить при сборке выпуска.

Другие вопросы по тегам