Регистратор пишет ошибку памяти что делать

Обновлено: 21.11.2024

ARM использует модель загрузки-сохранения для доступа к памяти, что означает, что только инструкции загрузки/сохранения (LDR и STR) могут получить доступ к памяти. В то время как в x86 большинству инструкций разрешено напрямую работать с данными в памяти, в ARM данные должны быть перемещены из памяти в регистры перед операцией. Это означает, что для увеличения 32-битного значения по определенному адресу памяти в ARM потребуется три типа инструкций (загрузка, увеличение и сохранение), чтобы сначала загрузить значение по определенному адресу в регистр, увеличить его в регистре и сохранить его обратно в память из регистра.

Чтобы объяснить основы операций загрузки и сохранения в ARM, мы начнем с простого примера и продолжим рассмотрение трех основных форм смещения с тремя разными режимами адресации для каждой формы смещения. Для каждого примера мы будем использовать один и тот же фрагмент ассемблерного кода с разными формами смещения LDR/STR, чтобы не усложнять задачу. Лучший способ следовать этой части руководства — запустить примеры кода в отладчике (GDB) в лабораторной среде.

  1. Форма смещения: непосредственное значение в качестве смещения
    • Режим адресации: смещение
    • Режим адресации: предварительно индексированный
    • Режим адресации: постиндексированный
  2. Форма смещения: зарегистрируйтесь как смещение
    • Режим адресации: смещение
    • Режим адресации: предварительно индексированный
    • Режим адресации: постиндексированный
  3. Форма смещения: масштабированный регистр как смещение
    • Режим адресации: смещение
    • Режим адресации: предварительно индексированный
    • Режим адресации: постиндексированный

Первый базовый пример

Как правило, LDR используется для загрузки чего-либо из памяти в регистр, а STR используется для сохранения чего-либо из регистра в адрес памяти.

Операция LDR: загружает значение по адресу, найденному в R0, в регистр назначения R2.

Операция STR: сохраняет значение, найденное в R2, по адресу памяти, найденному в R1.

Вот как это будет выглядеть в функциональной программе сборки:

Внизу у нас есть литеральный пул (область памяти в том же разделе кода для хранения констант, строк или смещений, на которые другие могут ссылаться независимым от позиции способом), где мы храним адреса памяти var1 и var2 ( определено в разделе данных вверху), используя метки adr_var1 и adr_var2. Первый LDR загружает адрес var1 в регистр R0. Второй LDR делает то же самое для var2 и загружает его в R1. Затем мы загружаем значение, хранящееся по адресу памяти, найденному в R0, в R2, и сохраняем значение, найденное в R2, по адресу памяти, найденному в R1.

Когда мы что-то загружаем в регистр, скобки ([ ]) означают: значение, найденное в регистре между этими скобками, является адресом памяти, из которого мы хотим что-то загрузить.

Когда мы сохраняем что-то в ячейке памяти, квадратные скобки ([]) означают: значение, найденное в регистре между этими скобками, является адресом памяти, по которому мы хотим что-то сохранить.

Звучит сложнее, чем есть на самом деле, поэтому вот наглядное представление того, что происходит с памятью и регистрами при выполнении приведенного выше кода в отладчике:

Давайте посмотрим на тот же код в отладчике.

Примечание: если вы забыли, почему действующий ПК расположен на две инструкции впереди текущей, это описано в Части 2 [… Во время выполнения ПК сохраняет адрес текущей инструкции плюс 8 (две инструкции ARM) в состоянии ARM и текущая инструкция плюс 4 (две инструкции Thumb) в состоянии Thumb. Это отличается от x86, где ПК всегда указывает на следующую выполняемую команду…].

1. Форма смещения: непосредственное значение в качестве смещения

Здесь мы используем непосредственное (целое) значение в качестве смещения. Это значение добавляется или вычитается из базового регистра (R1 в приведенном ниже примере) для доступа к данным со смещением, известным во время компиляции.

Давайте назовем эту программу ldr.s, скомпилируем ее и запустим в GDB, чтобы посмотреть, что произойдет.

В GDB (с помощью gef) мы устанавливаем точку останова на _start и запускаем программу.

Регистры в моей системе теперь заполнены следующими значениями (имейте в виду, что эти адреса могут отличаться в вашей системе):

Вот абстрактная иллюстрация того, что происходит:

2. Форма смещения: Зарегистрируйтесь как смещение.

В этой форме смещения в качестве смещения используется регистр. Пример использования этой формы смещения — когда ваш код хочет получить доступ к массиву, где индекс вычисляется во время выполнения.

После выполнения первой операции STR в режиме адреса смещения значение R2 (0x00000003) будет сохранено по адресу памяти 0x0001009c + 0x00000003 = 0x0001009F.

Вторая операция STR с режимом предварительно индексированного адреса будет делать то же самое, с той разницей, что она обновит базовый регистр (R1) вычисленным адресом памяти (R1+R2).

Последняя операция LDR использует режим постиндексированного адреса и загружает значение по адресу памяти, найденному в R1, в регистр R2, затем обновляет базовый регистр R1 (R1+R2 = 0x1009f + 0x3 = 0x100a2).

3. Форма смещения: масштабированный регистр как смещение

Третья форма смещения имеет масштабированный регистр в качестве смещения. В этом случае Rb является базовым регистром, а Rc является непосредственным смещением (или регистром, содержащим непосредственное значение), сдвинутым влево/вправо ( ) для масштабирования непосредственного. Это означает, что переключатель баррель используется для масштабирования смещения. Примером использования этой формы смещения может быть цикл для перебора массива. Вот простой пример, который вы можете запустить в GDB:

Обзор

Запомните три режима смещения в LDR/STR:

Как запомнить разные режимы адресов в LDR/STR:

LDR используется не только для загрузки данных из памяти в регистр. Иногда вы увидите такой синтаксис:

Загрузка немедленных значений в регистр на ARM не так проста, как на x86. Существуют ограничения на то, какие непосредственные значения вы можете использовать. Что это за ограничения и как с ними бороться — не самая захватывающая часть сборки ARM, но потерпите меня, это просто для вашего понимания, и есть приемы, которые вы можете использовать, чтобы обойти эти ограничения (подсказка: LDR). < /p>

Мы знаем, что каждая инструкция ARM имеет длину 32 бита и все инструкции являются условными. Есть 16 кодов условий, которые мы можем использовать, и один код состояния занимает 4 бита инструкции. Затем нам нужны 2 бита для регистра назначения. 2 бита для регистра первого операнда и 1 бит для флага set-status, а также различное количество битов для других вещей, таких как фактические коды операций. Дело в том, что после назначения битов типам инструкций, регистрам и другим полям для непосредственных значений остается только 12 битов, что позволяет использовать только 4096 различных значений.

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

Вот несколько примеров допустимых и недопустимых непосредственных значений:

Это приводит к тому, что невозможно загрузить полный 32-битный адрес за один раз. Мы можем обойти это ограничение, используя один из следующих двух вариантов:

Если вы попытаетесь собрать этот код, ассемблер выдаст ошибку:

Вам нужно либо разделить 511 на несколько частей, либо использовать LDR, как я описал ранее.

В этой статье описываются параметры файла дампа памяти для Windows.

Применимо к: Windows 7 с пакетом обновления 1, Windows Server 2012 R2
Исходный номер базы знаний: 254649

Обзор

Для записи отладочной информации можно настроить следующие операционные системы:

Отладочная информация может быть записана в файлы различных форматов (также называемые файлами дампа памяти), когда компьютер неожиданно останавливается из-за стоп-ошибки (также известной как синий экран, системный сбой или проверка ошибок). Вы также можете настроить Windows так, чтобы отладочная информация не записывалась в файл дампа памяти.

Windows может создать любой из следующих типов файлов дампа памяти:

  • Полный дамп памяти
  • Дамп памяти ядра
  • Небольшой дамп памяти (64 КБ)

Полный дамп памяти

Полный дамп памяти записывает все содержимое системной памяти, когда компьютер неожиданно останавливается. Полный дамп памяти может содержать данные процессов, которые выполнялись на момент создания дампа памяти.

Если вы выбрали вариант Полный дамп памяти, на загрузочном томе должен быть файл подкачки, достаточный для хранения всей физической оперативной памяти плюс 1 мегабайт (МБ).

Если выполняются следующие условия, предыдущий файл перезаписывается.

  • Возникает вторая проблема.
  • Создается еще один файл полного дампа памяти (или дампа памяти ядра).
  • В Windows 7 файл подкачки может находиться в разделе, отличном от раздела, на котором установлена ​​операционная система.
  • В Windows 7 нет необходимости использовать запись реестра DedicatedDumpFile, чтобы поместить файл подкачки в другой раздел.
  • Функция «Полный дамп памяти» недоступна на компьютерах с 32-разрядной операционной системой и объемом оперативной памяти 2 гигабайта (ГБ) или более.Дополнительные сведения см. в разделе Указание действий при неожиданной остановке системы.

Дамп памяти ядра

Дамп памяти ядра записывает только память ядра. Это ускоряет процесс записи информации в журнал, когда ваш компьютер неожиданно останавливается. У вас должен быть достаточно большой файл подкачки, чтобы вместить память вашего ядра. Для 32-разрядных систем объем памяти ядра обычно составляет от 150 МБ до 2 ГБ.

Этот файл дампа не включает нераспределенную память или память, выделенную для программ пользовательского режима. Он включает в себя:

  • Память, выделенная ядру и уровню аппаратной абстракции (HAL) в Windows 2000 и более поздних версиях.
  • Память, выделенная для драйверов режима ядра и других программ режима ядра.

Для большинства целей этот файл дампа наиболее полезен. Он меньше, чем полный файл дампа памяти. Но он пропускает только те части памяти, которые вряд ли были задействованы в проблеме.

Если выполняются следующие условия, предыдущий файл перезаписывается, когда установлен флажок Перезаписывать любой существующий файл.

  • Возникает вторая проблема.
  • Создается еще один файл дампа памяти ядра (или полный файл дампа памяти).

Небольшой дамп памяти

Небольшой дамп памяти записывает наименьший набор полезной информации, которая может помочь определить, почему ваш компьютер неожиданно остановился. Этот параметр требует наличия файла подкачки размером не менее 2 МБ на загрузочном томе и указывает, что Windows 2000 и более поздние версии создают новый файл каждый раз, когда компьютер неожиданно останавливается. История этих файлов хранится в папке.

Этот тип файла дампа включает следующую информацию:

  • Стоп-сообщение, его параметры и другие данные
  • Список загруженных драйверов
  • Контекст процессора (PRCB) для остановленного процессора
  • Информация о процессе и контекст ядра (EPROCESS) для остановленного процесса
  • Информация о процессе и контекст ядра (ETHREAD) для остановленного потока
  • Стек вызовов режима ядра для остановленного потока

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

Если выполняются следующие условия, предыдущий файл сохраняется.

  • Возникает вторая проблема.
  • Создается второй небольшой файл дампа памяти.

Каждому дополнительному файлу присваивается отдельное имя. Дата закодирована в имени файла. Например, Mini022900-01.dmp — это первый дамп памяти, созданный 29 февраля 2000 г. Список всех файлов небольших дампов памяти хранится в папке %SystemRoot%\Minidump.

Настроить тип дампа

Чтобы настроить параметры запуска и восстановления (включая тип дампа), выполните следующие действия.

Поскольку существует несколько версий Windows, следующие шаги могут отличаться на вашем компьютере. Если это так, см. документацию по продукту, чтобы выполнить эти действия.

  1. Нажмите "Пуск" и выберите "Панель управления".
  2. Нажмите "Производительность и обслуживание", а затем нажмите "Система".
  3. На вкладке "Дополнительно" нажмите "Параметры" в разделе "Запуск и восстановление".

Чтобы изменения вступили в силу, необходимо перезапустить Windows.

Инструменты для различных типов дампов

Вы можете загрузить полные дампы памяти и дампы памяти ядра с помощью стандартных символьных отладчиков, таких как I386kd.exe. I386kd.exe содержится на компакт-диске поддержки Windows 2000.

Загружайте небольшие дампы памяти с помощью Dumpchk.exe. Вы также можете использовать Dumpchk.exe для проверки правильности создания файла дампа памяти.

Определения тома

Загрузочный том. Том, содержащий операционную систему Windows и вспомогательные файлы. Загрузочный том может, но не обязательно, совпадать с системным томом.

Значения реестра для запуска и восстановления

Следующее значение реестра используется в HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\CrashControl .

  • CrashDumpEnabled REG_DWORD 0x0 = нет
  • CrashDumpEnabled REG_DWORD 0x1 = полный дамп памяти
  • CrashDumpEnabled REG_DWORD 0x2 = дамп памяти ядра
  • CrashDumpEnabled REG_DWORD 0x3 = небольшой дамп памяти (64 КБ)
  • CrashDumpEnabled REG_DWORD 0x7 = автоматический дамп памяти

Дополнительные значения реестра для CrashControl:

Автоперезагрузка REG_DWORD 0x1

Файл дампа REG_EXPAND_SZ %SystemRoot%\Memory.dmp

LogEvent REG_DWORD 0x1

Каталог минидампа REG_EXPAND_SZ %SystemRoot%\Minidump

Перезаписать REG_DWORD 0x1

Отправить оповещение REG_DWORD 0x1

Чтобы изменения вступили в силу, необходимо перезапустить Windows.

Протестируйте, чтобы убедиться, что файл дампа может быть создан

Дополнительную информацию о том, как настроить компьютер для создания файла дампа для целей тестирования, см. в разделе Функция Windows, позволяющая создавать файл дампа памяти с помощью клавиатуры.

Параметры типа дампа по умолчанию

  • Windows 7 (все выпуски): дамп памяти ядра
  • Windows Server 2012 R2 (все выпуски): Automatic memory.dmp

Максимальный размер файла подкачки

Максимальный размер файла подкачки ограничен следующим образом:

td>
Ограничение x86 x64 IA-64
Максимальный размер файла подкачки 4 гигабайта (без PAE)
16 терабайт (PAE)
16 терабайт32 терабайта
Максимальное количество файлов подкачки 16 16 16
Общий размер файла подкачки 64 гигабайта (без PAE)
256 терабайт (PAE)
256 терабайт 512 терабайт

Техническая поддержка 64-разрядных версий Windows

Производитель вашего оборудования предоставляет техническую поддержку и помощь для 64-разрядных версий Windows. Производитель вашего оборудования предоставляет поддержку, поскольку 64-разрядная версия Windows входит в комплект поставки вашего оборудования. Производитель вашего оборудования мог настроить установку Windows с уникальными компонентами. Уникальные компоненты могут включать в себя определенные драйверы устройств или дополнительные параметры для повышения производительности оборудования. Microsoft окажет разумную помощь, если вам потребуется техническая помощь по 64-разрядной версии Windows. Однако, возможно, вам придется связаться с производителем напрямую. Ваш производитель лучше всего подходит для поддержки программного обеспечения, установленного производителем на оборудовании.

Ошибки, о которых сообщает проверка во время выполнения, обычно делятся на две категории. Доступ к ошибкам и утечкам.

Ошибки доступа

Когда проверка доступа включена, проверка во время выполнения обнаруживает и сообщает об ошибках следующих типов.

Плохая бесплатная (baf) ошибка

Проблема: попытка освободить память, которая никогда не выделялась.

Возможные причины: передача указателя данных, не относящегося к куче, в free() или realloc().

Ошибка дублирования (duf)

Проблема: попытка освободить блок кучи, который уже был освобожден.

Возможные причины: вызов free() более одного раза с одним и тем же указателем. В C++ использование оператора удаления более одного раза для одного и того же указателя.

Ошибка неправильного выравнивания (maf)

Проблема: попытка освободить смещенный блок кучи.

Возможные причины: передача неправильно выровненного указателя в free() или realloc(); изменение указателя, возвращаемого malloc.

Ошибка неправильного чтения (mar)

Проблема: попытка прочитать данные с адреса без правильного выравнивания.

Возможные причины: чтение 2, 4 или 8 байтов из адреса, который не выровнен по полуслову, слову или двойному слову соответственно.

Ошибка неправильной записи (maw)

Проблема: попытка записи данных по адресу без правильного выравнивания.

Возможные причины: запись 2, 4 или 8 байтов по адресу, который не выровнен по полуслову, слову или двойному слову соответственно.

Ошибка нехватки памяти (oom)

Проблема: попытка выделить память за пределами доступной физической памяти.

Причина: программа не может получить больше памяти от системы. Полезно для обнаружения проблем, возникающих, когда возвращаемое значение из malloc() не проверяется на NULL, что является распространенной ошибкой программирования.

Ошибка чтения из массива за пределами границ (rob)

Проблема: попытка чтения массива за пределами памяти.

Возможные причины: Блуждающий указатель, выходящий за пределы блока кучи

Ошибка чтения из нераспределенной памяти (rua)

Проблема: попытка чтения из несуществующей, нераспределенной или неотображенной памяти.

Возможные причины: блуждающий указатель, выход за пределы блока кучи или доступ к уже освобожденному блоку кучи.

Ошибка чтения из неинициализированной памяти (rui)

Проблема: попытка чтения из неинициализированной памяти.

Возможные причины: чтение локальных данных или данных кучи, которые не были инициализированы.

Ошибка записи в массив за пределами памяти (wob)

Проблема: попытка записи в массив за пределами памяти.

Возможные причины: Блуждающий указатель, выходящий за пределы блока кучи

Ошибка записи в постоянную память (wro)

Проблема: попытка записи в постоянную память.

Возможные причины: запись по текстовому адресу, запись в раздел данных, доступный только для чтения (.rodata), или запись на страницу, которую mmap сделал доступной для чтения. только.

Ошибка записи в нераспределенную память (wua)

Проблема: попытка записи в несуществующую, нераспределенную или неотображенную память.

Возможные причины: блуждающий указатель, выход за границы блока кучи или доступ к уже освобожденному блоку кучи.

Ошибки утечки памяти

При включенной проверке утечек проверка во время выполнения сообщает об ошибках следующих типов.

Ошибка адреса в блоке (aib)

Проблема: возможная утечка памяти. Нет ссылки на начало выделенного блока, но есть хотя бы одна ссылка на адрес внутри блока.

Возможные причины: увеличивается единственный указатель на начало блока.

Ошибка адреса в регистре (air)

Проблема: возможная утечка памяти. Выделенный блок не был освобожден, и нигде в программной памяти нет ссылки на блок, но ссылка существует в регистре.

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

Ошибка утечки памяти (mel)

Проблема: выделенный блок не был освобожден, и нигде в программе нет ссылки на этот блок.

Читайте также: