Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шпоры_ТП (с рамками)_2013.docx
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
253.1 Кб
Скачать

40. Ошибки программирования: переполнение буфера. Понятие безопасного программного кода.

Переполнение буфера это проблема, характерная для языков 3-го поколения. Смыл проблемы заключается в том, что программа может записать данные за пределы выделенного в памяти буфера, что может привести к дальнейшим ошибкам в работе программы. Различают два основных варианта переполнения: “сверху” (overrun) и “снизу” (underrun). Оба варианта могут иметь место на организации буфера в виде “стека” или “кучи”.

Рассмотрим принцип появления проблемы на примере переполнения “сверху” в стеке. Регистр ESP указывает на вершину стека. При вызове некоторой подпрограммы, он, как правило, будет указывать на адрес кода возврата. Допустим, что при вызове данной подпрограммы необходимо передать в качестве параметра строку длиной 10 символов. Однако, при передаче было передано большее количество символов (например 12). Компилятор выделит в стеке 10 байт памяти под массив символов. Соответственно, адрес возврата сместится вглубь стека, и за ним встанет выделенный объем памяти. В момент передачи параметра, первые 10 символов запишутся в выделенный объем памяти, а оставшиеся 2 байта затрут в стеке значение адреса кода возврата. Т.о., значение адреса кода возврата изменится. По окончанию работы подпрограммы, сначала из стека выгрузятся (уничтожаться) все выделенные раннее структуры памяти. Так, адрес возврата снова “спустится” к выходу из стека, и регистр ESP будет указывать именно на него. Однако, значение было изменено. Компилятор интерпретирует его уже как другой адрес и сделает по нему возврат, что и будет составлять главную проблему.

Такая ошибка типична, и часто используема. Существуют случаи, преднамеренного использования такой ошибки в целях НСД, нарушения данных и т.д. Вызов методов подстраивался таким образом, чтобы по окончанию их работы, управление передавалось на другие вредоносные программы или вызов WinApi методов (создание нового администратора, наделение пользователя Guest администраторскими правами и т.д.).

Безопасное программирование – это такой метод разработки программ, при котором программисты допускают, что в их программах могут быть необнаруженные ошибки или противоречия. В процессе изменения программы для проверки состояния системы включаются избыточные коды, чтобы гарантировать, что изменения непротиворечивы. Если противоречия обнаружены, от изменений отказываются или состояние восстанавливается до известного корректного состояния.

Безопасный программный код – это программный код, написанный с использованием методов безопасного программирования.

41. Оптимизация программного кода. Основные возможности оптимизации кода программистом и компилятором.

Оптимизация программного кода называют изменение корректного кода, направленное на повышение его эффективности. «Оптимизация» подразумевает внесение небольших изменений, затрагивающих один класс, один метод, а чаще всего – несколько строк кода. Крупномасштабные изменения проекта или другие высокоуровневые способы повышения производительности оптимизацией не считаются. Это не самый эффективный способ повышения производительности. Улучшение архитектуры программы, перепроектирование классов и выбор более эффективного алгоритма - приводят к более впечатляющим результатам. Кроме того, оптимизация кода не самый легкий способ повысить производительность: легче купить новое оборудование или компилятор с улучшенным модулем оптимизации. Наконец, это не самый дешевый способ повысить производительность: на оптимизацию кода вручную изначально уходит много времени, а потом оптимизированный код труднее сопровождать.

Оптимизация программистом.

1). Расширить структуру данных добавлением дополнительной информации или изменить представление данных в этой структуре. 2). Вычисление результатов заранее и их хранение, для последующего использования. 3). Применение упаковки данных. 4). Внутренний цикл должен содержать min воз­можное количество проверок, а лучше всего только одну. 5). Удаление безусловных переходов. 6). Логические проверки должны быть располо­жены так, чтобы более быстрые условия, которые чаще оказываются пра­вильными, стояли перед более медленными условиями, которые реже оказываются правильными. 7). Логическая функция на небольшом множестве исходных значений может быть заменена таблицей, представляющей это множество. 8). Удаление одинаковых выражений. 9). Если два и более одинаковых выражения часто вычисляются подряд, их следует вынести в подпрограмму. 10). Изменение типов данных может оказаться эффективным способом сокращения кода и повышения его быстродействия. 11). Переписывание кода на низкоуровневом языке. При низком быстродействии код следует переписать на языке низкого уровня. Если вы пишите на С++, языком низкого уровня может быть Assembler. Переписывание кода на низкоуровневом языке обычно положительно влияет на быстродействие кода.

Оптимизация компилятором.

Методы оптимизации кода могут применяться на разных уровнях синтаксических конструкций: 1). на уровне оператора - большинство компиляторов выполняют некоторую оптимизацию на этом уровне. 2). на уровне блока – оптимизирующий компилятор выделяет операционную структуру программе путем конструирования ориентированного потокового графа программы, в кот каждая вершина представляет основной блок, а связи м/у вершинами представляют потоки управления. Большинство компиляторов производят оптимизацию на уровне блока. 3). на уровне цикла. 4). на уровне программы - наиболее сложный уровень оптимизации.

Чем выше уровень оптимизации, тем больше возможностей повышения быстродействия программного модуля. Однако затраты на применение большей степени оптимизации могут значительно увеличить время компиляции.