Управление памятью в Windows, страница 3

    //Перехват ошибок

            catch (unsigned int code)

    {

      printf("\nСгенерировано исключение");

              printf("\nКод исключения: code=%x",code);

      if (code!=0xC0000005)

              {

            printf("\nНеизвестное исключение");

      }

      if (code==0xC0000005)

              {

            printf("\nТекст исключения: Попытка записи в защищённую область памяти");

      }

              // проверка: находится ли индекс в нужном диапазоне

      if (i>=32*Kb)

      {

         printf("Попытка доступа к ячейке за границами буфера\n");

      }

    }

  _set_se_translator(oldhandler);

  getchar();

  if (p1) freebuffer(p1);

  if (p2) freebuffer(p2);

  if (p3) freebuffer(p3);

}

Результат работы программы показан на рис. 3.

Рис. 3. Работа примера 3


Индивидуальное задание

Зарезервировать  память 30 Мбт. Выделяя порциями необходимую память считать в нее последовательно от 1 до 20 дискет. Найти контрольную сумму считанных байтов. Записать эти дискеты на винчестер в файлы в виде отдельных образов.

Алгоритм работы программы

Первой частью задания было резервирование памяти в 30Мб. Для этого воспользовались функцией VirtualAlloc:

        
LPVOID VirtualAlloc(
LPVOID lpAddress, 
DWORD dwSize, 
DWORD flAllocationType, 
DWORD flProtect 
); 

Parameters

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

dwSize размер памяти для выделения

flAllocationType тип выделения (MEM_COMMIT, MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN)

flProtect тип доступа (PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE, E_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD)

Return Values

NULL – ошибка.

Для изменения типа доступа VirtualProtect:

BOOL VirtualProtect( 
LPVOID lpAddress, 
DWORD dwSize, 
DWORD flNewProtect, 
PDWORD lpflOldProtect 
); 

Parameters

lpAddress начальный адрес защищаемой области памяти

dwSize размер памяти для изменения

flNewProtect

устанавливаемый тип защиты (PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE, E_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD)

lpflOldProtect указатель на переменную для сохранения предведущего типа доступа

Return Values

Не NULL все нормально.

Для освобождения памяти VirtualFree:

BOOL VirtualFree(
LPVOID lpAddress, 
DWORD dwSize, 
DWORD dwFreeType 
); 

Parameters

lpAddress начальный адрес освобождаемой области (должен быть получен функцией VirtualAlloc)

dwSize размер освобождаемой области в байтах

dwFreeType тип освобождения памяти (MEM_DECOMMIT, MEM_RELEASE).

Return Values

Не NULL – все нормально.

Текст программы

#include <windows.h>

#include <stdio.h>

#include <iostream.h>

#define MEGABYTE 1048576

#define MSIZE 30

void main (void)

{

int startinglogicalsector=0, //номер сектора, с которого начнется чтение 

numberofsectors=1; // кличество читаемых секторов

DWORD bytesread;               // вспомог. ячейка

char drive_name[] = "\\\\.\\a:"; //имя дисковода А:

HANDLE hFile;

int ii=0;

//Зарезервируем 30 Мб памяти

PBYTE buff=(PBYTE)VirtualAlloc(NULL, MSIZE*MEGABYTE,MEM_RESERVE, PAGE_READWRITE);

while(ii<20)

{

MessageBox(0,"вставте дискетку", NULL, MB_OK);

// открыть дисковое устройство как файл

hFile=CreateFile(drive_name,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,0,NULL);

if(hFile==INVALID_HANDLE_VALUE)

{

MessageBox(0,"Открыть устройство не удалось",NULL,MB_OK|MB_ICONSTOP);

return;

}

//установить начальную точку чтения в файле на начало заданного сектора

SetFilePointer(hFile, 512*startinglogicalsector, 0, FILE_BEGIN);

// выделить память для результата чтения 

VirtualAlloc(buff, numberofsectors*512, MEM_COMMIT, PAGE_READWRITE);

// читать данные с устройства

if(!ReadFile(hFile, buff,numberofsectors*512, &bytesread, NULL))

{

VirtualFree(buff,MSIZE*MEGABYTE,NULL);

MessageBox(0,"Чтение данных НЕ удалось", NULL, MB_OK|MB_ICONSTOP);

return;

}

// закрыть файл (устройство) 

CloseHandle(hFile);

// распечатать результаты в 16-ти ричной форме

int j=0;

for (int i=0; i<512; i++)

{if (buff[i]<16) printf("%c", '0');

printf("%X ", buff[i]);

j++;

if (j>15) {j=0; printf("\n"); }

}

ii++;

}

VirtualFree(buff,MSIZE*MEGABYTE,NULL);

MessageBox(0,"OK!!!", "Результат", MB_OK);

}

Результат работы программы показан на рис. 4.

Рис. 4. Пример работы программы

Рис. 5. Ошибка чтения

Cписок использованных источников

1. Р.САЙМОН, WINDOWS  2000 API ЭНЦИКЛОПЕДИЯ  ПРОГРАММИСТА, 2002

2. Тихомиров В.А., Тихомиров В.А. Маленькие Уроки большого API

3. Рихтер Д., Рихтер Д. Создание эффективных WIN32-приложений, 2001