Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: 6468
Последний выпуск: 19.06.2015

VirtualAlloc

11K
25 ноября 2005 года
serijvolk
20 / / 22.11.2005
Цитата:
1. С помощью вызова функции
VOID GetSystemInfo( LPSYSTEM_INFO lpSystemInfo ); определяются гранулярность выделения и размер страницы виртуальной памяти;
2. Резервируется регион адресного пространства минимально допустимого размера и одной странице этого региона передается физическая память;
3. В начало этой страницы записываются целое число со значением 1234 и число типа double со значением 3.14, а далее за ними массив из восьми структур следующего типа: struct MyStruct { char charVal; int intVal[ 500 ]; }; Числа и структуры в массив записывать не копированием памяти, а с помощью указателей.
В самой первой структуре массива переменная charVal должна содержать код символа ‘A’, а в каждой следующей код символа должен быть на единицу больше, чем в предыдущей. Последний элемент массива intVal должен содержать индекс соответствующей структуры в массиве.
Чтобы сообразить, как записать в полученную память значения отдельных переменных или массивов, вспомните, например, как выделяется память для массива из двух целых чисел средствами языка С и как элементам этого массива присваиваются значения. Вот пример:
int *mas = (int*)calloc( 2, sizeof( int ) );
mas[ 0 ] =123;
mas[ 1 ] = 456;
4. Одной страницы памяти недостоточно для размещения всех структур, поэтому в програме необходимо написать обработчик исключений для передачи программе очередной страницы при попытке записи в область виртуальной памяти, которой физическая память еще не передана.
5. По завершении записи каждой очередной структуры на экран надо вывести в одну строку значения индекса структуры, текущее число переданных страниц физической памяти, значения charVal и последнего элемента массива intVal, адрес начала структуры и адрес начала массива intVal.

11K
25 ноября 2005 года
serijvolk
20 / / 22.11.2005
for (i=0; i < PAGELIMIT*dwPageSize; i++)
{
__try
{
lpPtr ='a';
}
__except ( PageFaultExceptionFilter( GetExceptionCode() ) )
{
ExitProcess( GetLastError() );

}
}
Весь код на msdn.com
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/reserving_and_committing_memory.asp

Мне нужно узнать как передать переменные в вирт. память. Ну никак не получается:(
403
28 ноября 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by serijvolk
Мне нужно узнать как передать переменные в вирт. память. Ну никак не получается:(



Ну это можно сделать примерно так. Ты наконец выделил нужную страницу и получил указатель на ее начальный адрес
Допустим имеем пару переменных:
....
LPVOID lpbase=VirtualAlloc(...);

int i=1;
double d=3.4f;
struct gg{
int i1;
char h[100];
};
//записываем последовательно произвольные данные в участок памяти
*(DOUBLE*)(lpbase)=d;//записываем double
((BYTE&)lpbase)+=sizeof(d);//+8 bytes смещение базового адреса на размер переменной

*(int*)(lpbase)=i;//записываем int
((BYTE&)lpbase)+=sizeof(i);//+4 bytes

gg op={0};
*(gg*)(lpbase)=op;//записываем структуру
((BYTE&)lpbase)+=sizeof(op);//+ 104 bytes

//считаем к примеру в обратном порядке из участка памяти с нашими данными в новые переменные
gg op2={0};
((BYTE&)lpbase)-=sizeof(op); //- 104 bytes
memcpy(&op2,lpbase,sizeof(op));

((BYTE&)lpbase)-=sizeof(i);//-4 bytes
int i2=*(int*)(lpbase);

((BYTE&)lpbase)-=sizeof(d);//-8 bytes
double d2=*(DOUBLE*)(lpbase);

Надеюсь понятно что дело в смещении и преобразовании типов базового адреса . В принципе можно и без преобразований используя один memcpy

11K
01 декабря 2005 года
serijvolk
20 / / 22.11.2005
*(DOUBLE*)(lpvBase)=pi; --> error C2440: '=' : cannot convert from 'double *' to 'double'
memcpy(lpvBase,pi,sizeof(pi)); --> если я правильно задал.. ошибка Access Violation
403
01 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by serijvolk
*(DOUBLE*)(lpvBase)=pi; --> error C2440: '=' : cannot convert from 'double *' to 'double'
memcpy(lpvBase,pi,sizeof(pi)); --> если я правильно задал.. ошибка Access Violation



error C2440:
это могло возникнуть только если pi было обявлено как: double *pi;
а надо: double pi;

во вторых раз при у тя pi указатель,а это скорее всего так как у тя компилится memcpy(lpvBase,pi,sizeof(pi)); без ошибок. так как еслиб это не был указатель то функция у тя имела бы вид
memcpy(lpvBase,&pi,sizeof(pi)); А так все правильно в твоем случае выдает ошибку так как не может прочитать указаные по указателю данные под которые скорее всего память не была выделена,либо не была выделена память под lpvBase. Короче определи переменную pi:
double pi;

и все в обоих случаях будет ок.

11K
01 декабря 2005 года
serijvolk
20 / / 22.11.2005
Но мне же надо
Цитата:
Числа и структуры в массив записывать не копированием памяти, а с помощью указателей.

403
01 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by serijvolk
Но мне же надо


ну тогда можно к примеру так:
double *pi=new double;
*pi=3.14f;
*(DOUBLE*)(lpbase)=*pi;

или так:
double dpi=3.14f;
double *pi=&dpi;
*(DOUBLE*)(lpbase)=*pi;



вот те и с указателями.

11K
02 декабря 2005 года
serijvolk
20 / / 22.11.2005
if (!(lpvBase = VirtualAlloc( NULL,sSysInfo.dwPageSize,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE)))
printf("Pamjat' ne zarezervirovana\n");
*(DOUBLE*)(lpvBase)=*pi;
((BYTE&)lpvBase)+=sizeof(pi);
*(int*)(lpvBase)=*chislo;

переменную pi записывает, адресс lpvBase увеличивается на размер pi, но почему то chislo записывается по старому адрессу lpvBase, т.е. затирает начение pi. но думаю препод и так примет))
403
02 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by serijvolk
if (!(lpvBase = VirtualAlloc( NULL,sSysInfo.dwPageSize,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE)))
printf("Pamjat' ne zarezervirovana\n");
*(DOUBLE*)(lpvBase)=*pi;
((BYTE&)lpvBase)+=sizeof(pi);
*(int*)(lpvBase)=*chislo;

переменную pi записывает, адресс lpvBase увеличивается на размер pi, но почему то chislo записывается по старому адрессу lpvBase, т.е. затирает начение pi. но думаю препод и так примет))



да потому что ты неправильно получаеш размер записанных данных указателя на данные. Короче надо так:((BYTE&)lpvBase)+=sizeof(*pi);
или так ((BYTE&)lpvBase)+=sizeof(double);

а совсем не так ((BYTE&)lpvBase)+=sizeof(pi); так как в данном случае будет возвращяться размер указателя 4 вместо положенных для double 8

289
02 декабря 2005 года
Matush
726 / / 14.01.2004
Цитата:
Originally posted by vitaly2003s
.....
*(DOUBLE*)(lpbase)=d;
.....



Плохой, очень плохой код (голосом Green'а).

P.S. Я сам так пишу к сожалению (или к счастью).

403
02 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by Matush
Плохой, очень плохой код (голосом Green'а).

P.S. Я сам так пишу к сожалению (или к счастью).


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

11K
02 декабря 2005 года
serijvolk
20 / / 22.11.2005
Цитата:
Originally posted by vitaly2003s
Да сам знаю,пережиток Си,но здесь требуется довольно низкоуровневый доступ к данным так что данный код здесь вполне уместен,да и вариантов здесь немного.


Благодарю!:) А на счёт кода.. преподов надо учить новым языкам, что бы они могли нормально учить студентов. Ато препод хз когда выучил С потом посмотрел что в С++ и получил добро лечить студентов.

11K
03 декабря 2005 года
serijvolk
20 / / 22.11.2005
мле, в память записывается но почему то не ловит исключение что памяти не хватает - зарегить новую страницу... По перемиенной size (15988) видно что записаный byte существенно больше чем размер окна. Код:
Код:
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

#define kol 500

LPTSTR lpNxtPage; // address of the next page to ask for
DWORD dwPages = 1; // count of pages gotten so far
SYSTEM_INFO sSysInfo;
INT PageFaultExceptionFilter(DWORD dwCode)
{
LPVOID lpvResult;
if (dwCode != EXCEPTION_ACCESS_VIOLATION)
{
printf("\tOshibka dostupa\n");
return EXCEPTION_EXECUTE_HANDLER;
}
printf("\nOshibka razmeshenija stranici\n");
// Otherwise, commit another page.
lpvResult = VirtualAlloc((LPVOID) lpNxtPage, sSysInfo.dwPageSize,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE);
if (lpvResult == NULL )
{
printf("Pamjat' ne zarezervirovana\n");
return EXCEPTION_EXECUTE_HANDLER;
} else {
printf ("Razmeshchenie v drugoj stranice\n");
dwPages++;
lpNxtPage += sSysInfo.dwPageSize;
}
return EXCEPTION_CONTINUE_EXECUTION;
}

VOID main(VOID)
{
GetSystemInfo(&sSysInfo);
printf("PageSize: %d. Granularity: %d.\n", sSysInfo.dwPageSize,sSysInfo.dwAllocationGranularity);

struct MyStruct
{
char charVal;
int intVal[ kol ];
};
int *chislo= new int;
*chislo=1234;
double *pi=new double;
*pi=3.14;

MyStruct *arr = new MyStruct[8];
int i,i2;
DWORD bkvA=65;

arr[0].charVal=bkvA;
for(i2=0;i2<kol-1;i2++)
    arr[0].intVal[i2]=i2;
arr[0].intVal[kol-1]=0;
for(i=1; i<8; i++)
{
    for(i2=0;i2<kol-1;i2++)
        arr.intVal[i2]=i2;
    arr.intVal[kol-1]=i;
    bkvA++;
    arr.charVal=bkvA;
}

LPVOID lpvBase;

if (!(lpvBase = VirtualAlloc( NULL,sSysInfo.dwPageSize,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE)))
  printf("Pamjat' ne zarezervirovana\n");
lpNxtPage = (LPTSTR) lpvBase;
lpNxtPage += sSysInfo.dwPageSize;
*(DOUBLE*)(lpvBase)=*pi;
((BYTE&)lpvBase)+=sizeof(double);
*(int*)(lpvBase)=*chislo;
((BYTE&)lpvBase)+=sizeof(int);
int size=sizeof(double);
size+=sizeof(int);

for (i=0; i <8; i++)
{
__try
{
*(char*)(lpvBase)=arr.charVal;
((BYTE&)lpvBase)+=sizeof(char);
size+=sizeof(char);
for(i2=0;i2<kol-1;i2++)
{
    *(int*)(lpvBase)=arr.intVal[i2];
    ((BYTE&)lpvBase)+=sizeof(int);
    size+=sizeof(int);
}
printf("\nIndex=%d, Peredano=%d, charVal=%s, intVal[%d]=%d byte=%d", i,dwPages, &arr.charVal,kol-1,arr.intVal[kol-1],size);
}
__except ( PageFaultExceptionFilter( GetExceptionCode() ) )
{
    printf ("Error! %s!\n", (LPSTR) GetLastError ());
}
}
VirtualFree(lpvBase,0,MEM_RELEASE);
delete chislo;
delete pi;
delete []arr;
getch();
}
403
04 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
Напиши так и все будет ОК:
Код:
#define kol 500

LPVOID lpNxtPage; // address of the next page to ask for
DWORD dwPages = 1; // count of pages gotten so far
SYSTEM_INFO sSysInfo;
INT PageFaultExceptionFilter(DWORD dwCode)
{
    LPVOID lpvResult;
    if (dwCode != EXCEPTION_ACCESS_VIOLATION)
    {
        printf("\tOshibka dostupa\n");
        return EXCEPTION_EXECUTE_HANDLER;
    }
    printf("\nOshibka razmeshenija stranici\n");
    // Otherwise, commit another page.
    lpvResult = VirtualAlloc(lpNxtPage, sSysInfo.dwPageSize, MEM_COMMIT,PAGE_READWRITE);
    if (lpvResult == NULL )
    {
        printf("Pamjat' ne zarezervirovana\n");
        return EXCEPTION_EXECUTE_HANDLER;
    } else {
        printf ("Razmeshchenie v drugoj stranice\n");
        dwPages++;
        (DWORD&)lpNxtPage += sSysInfo.dwPageSize;
    }
    return EXCEPTION_CONTINUE_EXECUTION;
}

VOID main(VOID)
{
    GetSystemInfo(&sSysInfo);
    printf("PageSize: %d. Granularity: %d.\n", sSysInfo.dwPageSize,sSysInfo.dwAllocationGranularity);

    struct MyStruct {
        char charVal;
        int intVal[ kol ];
    };

    int *chislo= new int;
    *chislo=1234;

    double *pi=new double;
    *pi=3.14f;

    MyStruct *arr = new MyStruct[8];
    char bkvA=65;

    for(int i=0; i<8; i++) {
        for(int i2=0;i2<kol-1;i2++) arr.intVal[i2]=i2;
        arr.intVal[kol-1]=i;
        arr.charVal=bkvA++;
    }

    LPVOID lpvBase;

    //rezerviruem region iz 100 stranic
    if (!(lpvBase = VirtualAlloc( NULL,sSysInfo.dwPageSize*100,MEM_RESERVE,PAGE_NOACCESS)))
        printf("Pamjat' ne zarezervirovana\n");

    //передаем память первой странице
    if (!(lpvBase = VirtualAlloc( lpvBase,sSysInfo.dwPageSize,MEM_COMMIT,PAGE_READWRITE)))
        printf("Pamjat' ne videlena\n");

    lpNxtPage = lpvBase;
    (DWORD&)lpNxtPage += sSysInfo.dwPageSize;
    *(double*)(lpvBase)=*pi;
    ((DWORD&)lpvBase)+=sizeof(double);
    int size=sizeof(double);
    *(int*)(lpvBase)=*chislo;
    ((DWORD&)lpvBase)+=sizeof(int);
    size+=sizeof(int);

    for (i=0; i <8; i++)
    {
        __try
        {
            *(MyStruct*)(lpvBase)=arr;
            ((DWORD&)lpvBase)+=sizeof(MyStruct);
            size+=sizeof(MyStruct);
            printf("\nIndex=%d, Peredano=%d, charVal=%s, intVal[%d]=%d byte=%d", i,dwPages, &arr.charVal,kol-1,arr.intVal[kol-1],size);
        }
        __except ( PageFaultExceptionFilter( GetExceptionCode() ) )
        {
            printf ("Error! %s!\n", (LPSTR) GetLastError ());
        }
    }
    VirtualFree(lpvBase,0,MEM_RELEASE);
    delete chislo;
    delete pi;
    delete []arr;
    //getch();
}
11K
04 декабря 2005 года
serijvolk
20 / / 22.11.2005
тут резервация 100 страниц, а надо регить всего одну.
403
05 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by serijvolk
тут резервация 100 страниц, а надо регить всего одну.


Да нет,надо резервировать в твоем случае конечно не 100 а 4 по моему там у тя. Короче надо резервировать стоко памяти скоко предлогаемый будет весь объем данных. В противном случае преложенный механизм исключений может не сработать и ты можеш записать в чужую область данных своей программы.

11K
05 декабря 2005 года
serijvolk
20 / / 22.11.2005
т.е. резервировать память по мере необходимости нельзя? типа инфа будет находиться не одним куском в памяти а в разрозненом виде?.. если преподша не примет я веренусь;) :D
403
05 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by serijvolk
т.е. резервировать память по мере необходимости нельзя? типа инфа будет находиться не одним куском в памяти а в разрозненом виде?.. если преподша не примет я веренусь;) :D


Можно конечно,но не в данном случае. так как следующий адрес страницы ты знаеш наперед и ты пытаешся передать зарезервировать и передать ему память,и если вдруг оказалось что данный участок уже был зарезервирован и выделен кем то другим в твоем адресном пространстве,то VirtualAlloc даже не возвратит ошибки он те возвратит этот чужой адрес а ты будеш думать что все ок и писать поверх чужих данных. Так что лучше в таких случаях зарвнее резервировать участок памяти,это будет гарантией что все адреса в этом участке будут не заняты,да и к тому же резервирование участка памяти не означает что буде тратится виртуальная память,она тратится только когда ты передаеш память странице с помощью MEM_COMMIT.

11K
05 декабря 2005 года
serijvolk
20 / / 22.11.2005
Ах вот как оно работает:) Вроде соотв. требованиям. Будем здавать:D Спасибо!:)
11K
07 декабря 2005 года
serijvolk
20 / / 22.11.2005
Лаба здана и принята:) Thanks:)
15K
07 декабря 2005 года
Yusuke
1 / / 07.12.2005
to serijvolk
Слушай, а ты случайно не из Риги ? :)

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


Подскажите почему :(



Код:
int main(int argc, char* argv[])
{

...
...

    res = VirtualAlloc(NULL, si.dwAllocationGranularity, MEM_RESERVE, PAGE_READWRITE);
    res = VirtualAlloc(res, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE);

    if(res != NULL)
    {
        *(int *)res = a; // int a
        *(double*)((int *)res+1) = b;  // double b

        for(int i=0; i<8; i++)
        {
            __try
            {              
                *((MyStruct *)res+1+i) = mas;  // mas  eto massiv struktur
            }
            __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
            {
                addAlloc += 1;
                res = VirtualAlloc((LPVOID)((int *)res+1+i), si.dwPageSize, MEM_COMMIT, PAGE_READWRITE);
                *((MyStruct *)res+1+i) = mas;
            }
        }

        VirtualFree(res, si.dwPageSize*addAlloc, MEM_DECOMMIT);
    }

    return 0;
}
403
08 декабря 2005 года
vitaly2003s
481 / / 27.07.2004
приведи полностью код а там посмотрим

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог