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

            if (p&&valid)

            {

                        printf("Блок памяти: %xh", (unsigned int)p );

            }

            if (!p&&valid) cout<<ATO("Ошибка выделения памяти!\n");

  } while (1);

}

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

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

Пример 2. Определенно одним из основных преимуществ использования VirtualAlloc является возможность управления уровнем доступа к страницам оперативной памяти как во время ее выделения, так и позже (при помощи функции VirtualProtect). Разумное использование этой возможности может существенно упростить разработку многих приложений.

Для примера рассмотрим код в листинге 2. Это библиотечная функция, которая возвращает указатель на статическую строку. В реальной жизни эта функция может располагаться в библиотеке DLL, однако для целей этой программы мы включим ее в состав основного исполняемого файла наряду с функцией main.

Листинг 2. Передача статической строки в режиме только для чтения

#include <stdio.h>

#include <string.h>

#include <windows.h>

extern   "C"       int        printf_oem(const char *s, ... )

{

va_list ap;

va_start(ap,s);

char      src[256];

vsprintf(src,s,ap );

va_end(ap);

char      oems[256];

CharToOem(src,oems);

return printf(oems);

}

#define printf  printf_oem

char *getmsg()

{

static char *msg;

if (msg==NULL)

{

char tmp[1024];

DWORD oldprot;

FILE *f;

f=fopen("strings.txt", "r");

if (!f) return NULL;

fgets(tmp, sizeof(tmp), f);

// Выделяет целую страницу памяти, что приемлемо для данного примера

msg=(char *)VirtualAlloc(NULL, strlen(tmp)+1, MEM_COMMIT, PAGE_READWRITE);

strcpy(msg, tmp);

fclose(f);

// Назначает уровень доступа к странице памяти только для чтения

VirtualProtect(msg, strlen(msg)+1, PAGE_READONLY, &oldprot);

}

return msg;      

}

void main()

{

char *m=getmsg();

try {

printf("Вся строка: %s\n",m);

m=strtok(m," \t");

printf("token1=%s\n",m);

m=getmsg();

printf("Вся строка: %s\n",m);

}

catch (...)  // следить за любыми исключениями

{

printf("Произошло исключение!\n");

}

getchar();  // ожидание для отладочных целей

}

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

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

Листинг 3. Бесконечный буфер

#include <windows.h>

#include <stdio.h>

#include <eh.h>  // преобразование исключений C в исключения C++

extern   "C"       int        printf_oem(const char *s, ... )

{

            va_list ap;

    va_start(ap,s);

            char      src[256];

            vsprintf(src,s,ap );

    va_end(ap);

            char      oems[256];

            CharToOem(src,oems);

            return printf(oems);

}

#define printf  printf_oem

#define Kb 1024

void cppexcept( unsigned int u, _EXCEPTION_POINTERS* pExp )

{

    throw u;

}

char* getbuffer(long int IpvAddr)

{

            char *rv;

    rv= (char *)VirtualAlloc((LPVOID) IpvAddr, 32*Kb,MEM_COMMIT,PAGE_READWRITE);

            return rv;

}

void freebuffer(char *p)

{

    VirtualFree(p,0,MEM_RELEASE);

}

void main()

{          

            DWORD oldprot;

            char *p1=getbuffer(0x900000);

            char *p2=getbuffer(0x1000000);

            char *p3=getbuffer(0x3000000);

            if (p1) printf("\nВыделен блок памяти в 32 Кбайта по адресу: 0x%x",p1);

            else printf("\nНевозможно выделить память по адресу 0x900000");

            if (p2) printf("\nВыделен блок памяти в 32 Кбайта по адресу: %x",p2);

            else printf("\nНевозможно выделить память по адресу 0x1000000");

            if (p3) printf("\nВыделен блок памяти в 32 Кбайта по адресу: %x",p3);

            else printf("\nНевозможно выделить память по адресу 0x3000000");

    for (int i=0;i<32*Kb;i++)

    {

                        if (p1) p1[i]=1;

                        if (p2) p2[i]=1;

                        if (p3) p3[i]=1;

    }

            if (p1)     VirtualProtect(p1, 32*Kb, PAGE_READONLY, &oldprot);

            if (p2)     VirtualProtect(p2, 32*Kb, PAGE_READONLY, &oldprot);

            if (p3)   VirtualProtect(p3, 32*Kb, PAGE_READONLY, &oldprot);

            printf("\n\nЗащита памяти установлена");

    _se_translator_function oldhandler=_set_se_translator(cppexcept);

    //Попытка обнулить память

    printf("\n\nПопытка обнулить память...");

            try

            {

      for (i=0;i<32*Kb;i++)

              {

        p1[i]=0;

                        p2[i]=0;

                        p3[i]=0;

              }

    }