Здравствуйте, уважаемые коллеги-программисты.
У меня возникла следующая проблема с выделением памяти под массив структур:
одна и та же программа, скомпилированная разными компиляторами на разных машинах, но с одинаковым количеством ОЗУ и виртуальной памяти, не может выделить всю доступную память. При чем один и тот же компилятор на разных машинах выдает разные результаты. Особенно интересно то, что количество экземпляров, под которые выделяется память, никак не зависит от ее свободного на данный момент размера. И тем более странно, когда программа выделяет около 100 мегабайт памяти и не более, когда доступно более 500. Проверялось на системах с 1 и 2 GB памяти. Компиляторы: VC2003, VC2005, Borland 5.9.1.0
Это все касается Windows XP SP2. В Linux (Debian 4.0, ядро 2.6.18, компилятор gcc 4.1.1) программа выделяет под себя всю доступную память (в том числе из свапа), после чего убивается системой.
Комментарий к исхднику: объявляется структура из char* для строки и char** для массива строк, после чего до бесконечности выделяется память для структуры, char*, char**, и каждого элемента char** (10).
Ну и собственно исходник:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10
typedef struct sample
{
char *name;
char **list;
} sample;
int main ()
{
sample *samples;
unsigned int i = 0, j;
samples = (sample *)malloc (0);
while (1)
{
if (samples = (sample *)realloc (samples, (i + 1) * sizeof (sample)))
{
if ((samples + i)->name = (char *)calloc (300, 1))
strcpy ((samples + i)->name, "blablabla");
else
{
printf ("\nCouldn't allocate memory for samples->name\n");
break;
}
(samples + i)->list = (char **)malloc (0);
j = 0;
while (j++ < SIZE)
if ((samples + i)->list =
(char **)realloc ((samples + i)->list,
(j + 1) * sizeof (char *)))
if (*((samples + i)->list + j) = (char *)calloc (300, 1))
strcpy (*((samples + i)->list + j), "blablabla");
else
{
printf ("\nCouldn't allocate memory for samples->list item\n");
break;
}
else
{
printf ("\nCouldn't reallocate memory for samples->list\n");
break;
}
printf ("\r%d", i++);
}
else
{
printf ("\nCouldn't reallocate memory for samples *\n");
break;
}
}
system ("pause");
return 0;
}
Ну и вопрос: что я делаю неправильно? Ведь должен быть способ выделять ВСЮ память.
С уважением.
Вообще, ИМХО, единственный верный способ забыть про фрагментацию и прочие ограничения, свойственные реализациям куч — сразу выделить себе память в размере min(своп, виртуальное адресное пространство) и организовать на нем собственную стратегию размещения — ака переопределить new/delete.
Что касается проблемы с winxp — это очень похоже на проблему со стандартной кучей. Подобной болезнью страдают кучи в .NET на IA32 системы, и я подозреваю, что виноват виндовый механизм HeapAlloc/HeapFree, поскольку в .NET эта проблема IA32-систем так и не была устранена.
Здравствуйте, Dedaulus, Вы писали:
D>D> if (samples = (sample *)realloc (samples, (i + 1) * sizeof (sample)))
D> (char **)realloc ((samples + i)->list,
D>
Вот здесь трабл. Дело в том что в Windows realloc/LocalReAlloc/GlobalReAlloc может не сработать из-за фрагментации те если вы сдали еще один вызов LocalAlloc/GlobalAlloc то потом если делать ReAlloc на размер больший чем PAGE(вроде 4kb) то память не увеличиватся.
В Linux таких проблем нет, там realloc честно работает.
D>Ну и вопрос: что я делаю неправильно? Ведь должен быть способ выделять ВСЮ память.
Конечно можно: malloc(SizeOfAllMemory)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"Dedaulus" <69240@users.rsdn.ru> wrote in message
news:2658190@news.rsdn.ru...
> Здравствуйте, уважаемые коллеги-программисты.
>
> У меня возникла следующая проблема с выделением памяти под массив структур:
> одна и та же программа, скомпилированная разными компиляторами на разных машинах, но с одинаковым количеством ОЗУ и виртуальной памяти, не может выделить всю доступную память. При чем один и тот же компилятор на разных машинах выдает разные результаты. Особенно интересно то, что количество экземпляров, под которые выделяется память, никак не зависит от ее свободного на данный момент размера. И тем более странно, когда программа выделяет около 100 мегабайт памяти и не более, когда доступно более 500. Проверялось на системах с 1 и 2 GB памяти. Компиляторы: VC2003, VC2005, Borland 5.9.1.0
> Это все касается Windows XP SP2. В Linux (Debian 4.0, ядро 2.6.18, компилятор gcc 4.1.1) программа выделяет под себя всю доступную память (в том числе из свапа), после чего убивается системой.
Под XP можно позвать HeapSetInformation и потребовать low-fragmentation heap:
ULONG HeapFragValue = 2;
HeapSetInformation(GetProcessHeap(),HeapCompatibilityInformation,
&HeapFragValue, sizeof(HeapFragValue)
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.