динамическое выделение памяти под структуру
От: Dedaulus  
Дата: 14.09.07 21:11
Оценка: -1
Здравствуйте, уважаемые коллеги-программисты.

У меня возникла следующая проблема с выделением памяти под массив структур:
одна и та же программа, скомпилированная разными компиляторами на разных машинах, но с одинаковым количеством ОЗУ и виртуальной памяти, не может выделить всю доступную память. При чем один и тот же компилятор на разных машинах выдает разные результаты. Особенно интересно то, что количество экземпляров, под которые выделяется память, никак не зависит от ее свободного на данный момент размера. И тем более странно, когда программа выделяет около 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;
}



Ну и вопрос: что я делаю неправильно? Ведь должен быть способ выделять ВСЮ память.

С уважением.
Re: динамическое выделение памяти под структуру
От: Sni4ok  
Дата: 14.09.07 22:11
Оценка: +2
Здравствуйте, Dedaulus, Вы писали:

D>Ну и вопрос: что я делаю неправильно? Ведь должен быть способ выделять ВСЮ память.


с какой это радости? или вы забыли про фрагментацию?
на самом деле просто не представляю когда необходимо одним блоком такие куски > 10мб.. думаю есть смысл переделать архитектуру
и алгоритмы, чтобы такого не требовалось.
Re[2]: динамическое выделение памяти под структуру
От: Mr.Cat  
Дата: 14.09.07 23:37
Оценка: 2 (1)
Вообще, ИМХО, единственный верный способ забыть про фрагментацию и прочие ограничения, свойственные реализациям куч — сразу выделить себе память в размере min(своп, виртуальное адресное пространство) и организовать на нем собственную стратегию размещения — ака переопределить new/delete.

Что касается проблемы с winxp — это очень похоже на проблему со стандартной кучей. Подобной болезнью страдают кучи в .NET на IA32 системы, и я подозреваю, что виноват виндовый механизм HeapAlloc/HeapFree, поскольку в .NET эта проблема IA32-систем так и не была устранена.
Re: динамическое выделение памяти под структуру
От: ss_sa  
Дата: 15.09.07 07:22
Оценка: 2 (1) :)
Здравствуйте, 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>>
Re: динамическое выделение памяти под структуру
От: Sergey Россия  
Дата: 17.09.07 10:25
Оценка: 1 (1)
"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 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.