VirtualAlloc
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.
{
__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
Мне нужно узнать как передать переменные в вирт. память. Ну никак не получается:(
Мне нужно узнать как передать переменные в вирт. память. Ну никак не получается:(
Ну это можно сделать примерно так. Ты наконец выделил нужную страницу и получил указатель на ее начальный адрес
Допустим имеем пару переменных:
....
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
memcpy(lpvBase,pi,sizeof(pi)); --> если я правильно задал.. ошибка Access Violation
*(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;
и все в обоих случаях будет ок.
Но мне же надо
ну тогда можно к примеру так:
double *pi=new double;
*pi=3.14f;
*(DOUBLE*)(lpbase)=*pi;
или так:
double dpi=3.14f;
double *pi=&dpi;
*(DOUBLE*)(lpbase)=*pi;
вот те и с указателями.
printf("Pamjat' ne zarezervirovana\n");
*(DOUBLE*)(lpvBase)=*pi;
((BYTE&)lpvBase)+=sizeof(pi);
*(int*)(lpvBase)=*chislo;
переменную pi записывает, адресс lpvBase увеличивается на размер pi, но почему то chislo записывается по старому адрессу lpvBase, т.е. затирает начение pi. но думаю препод и так примет))
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
.....
*(DOUBLE*)(lpbase)=d;
.....
Плохой, очень плохой код (голосом Green'а).
P.S. Я сам так пишу к сожалению (или к счастью).
Плохой, очень плохой код (голосом Green'а).
P.S. Я сам так пишу к сожалению (или к счастью).
Да сам знаю,пережиток Си,но здесь требуется довольно низкоуровневый доступ к данным так что данный код здесь вполне уместен,да и вариантов здесь немного.
Да сам знаю,пережиток Си,но здесь требуется довольно низкоуровневый доступ к данным так что данный код здесь вполне уместен,да и вариантов здесь немного.
Благодарю!:) А на счёт кода.. преподов надо учить новым языкам, что бы они могли нормально учить студентов. Ато препод хз когда выучил С потом посмотрел что в С++ и получил добро лечить студентов.
#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();
}
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();
}
тут резервация 100 страниц, а надо регить всего одну.
Да нет,надо резервировать в твоем случае конечно не 100 а 4 по моему там у тя. Короче надо резервировать стоко памяти скоко предлогаемый будет весь объем данных. В противном случае преложенный механизм исключений может не сработать и ты можеш записать в чужую область данных своей программы.
т.е. резервировать память по мере необходимости нельзя? типа инфа будет находиться не одним куском в памяти а в разрозненом виде?.. если преподша не примет я веренусь;) :D
Можно конечно,но не в данном случае. так как следующий адрес страницы ты знаеш наперед и ты пытаешся передать зарезервировать и передать ему память,и если вдруг оказалось что данный участок уже был зарезервирован и выделен кем то другим в твоем адресном пространстве,то VirtualAlloc даже не возвратит ошибки он те возвратит этот чужой адрес а ты будеш думать что все ок и писать поверх чужих данных. Так что лучше в таких случаях зарвнее резервировать участок памяти,это будет гарантией что все адреса в этом участке будут не заняты,да и к тому же резервирование участка памяти не означает что буде тратится виртуальная память,она тратится только когда ты передаеш память странице с помощью MEM_COMMIT.
Слушай, а ты случайно не из Риги ? :)
Я сделал более простой вариант, но почему то она у меня только 1 раз обрабатывает исключение .
Подскажите почему :(
{
...
...
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;
}