Почему новый / malloc не работает на Win x64, хотя есть много свободной оперативной памяти? - PullRequest
3 голосов
/ 23 октября 2009

У меня есть сильно рекурсивная функция, которая создает (очень маленькое) std::multimap локально для каждого экземпляра функции, используя new (который возвращается к malloc/calloc в std lib). После нескольких сотен рекурсий новый сбой, хотя я использую родное 64-битное приложение на Windows XP x64. Машина имеет 10 ГБ оперативной памяти, приложение использует только около 1 ГБ. Другие большие приложения не работают.

Это происходит через несколько минут после запуска программы и запуска рекурсивной функции. В этот момент рекурсивная функция была вызвана около 150.000 раз, возможно, с максимальным значением. рекурсия нескольких сотен. Проблема не в переполнении стека.

Я использую Visual Studio 2005 и программное обеспечение STL. Ошибка возникает в сборке выпуска.

EDIT: Хорошо, вот код Теперь я переставил код и поместил карту в стек, но для инициализации он использует новое - там это не получается. Я также попытался использовать std :: multimap вместо hash_multimap. Все это умирает, не меняет своего поведения.

    int TraceBackSource(CalcParams *CalcData, CKnoObj *theKno, int qualNo, 
                            double maschFak, double partAmount, int MaschLevel, char *MaschID, 
                            double *totalStrFlow, int passNo, 
                            CTraceBackData *ResultData)

{   typedef std::hash_multimap<double, CStrObj *>StrFMap;
    StrFMap thePipes;

        for(...)
        {  
            ...
            thePipes.insert(std::make_pair(thisFlow, theStr));
        }

        // max. 5 elements in "thePipes"
        for(StrFMap::iterator it = thePipes.begin(); it != thePipes.end(); it++)
        {
            ...
            try
            {
                TraceBackSource(CalcData, otherKno, qualNo, maschFak * nodeFak, nodeAmount, SubMaschlevel, newMaschID, totalStrFlow, passNo, ResultData);
            }
            catch(std::exception &it)
            {   
                    Trace(0, "*** Exception, %s", it.what()); 
                    return 0;
            }

            return 0;
        }
}

Интересно, что первый сбой встречается с обработчиком перехвата, чуть позже я заканчиваю НАРУШЕНИЕ ДОСТУПА и поврежденный стек.

Ответы [ 4 ]

3 голосов
/ 23 октября 2009

Объем оперативной памяти на вашем компьютере и других запущенных процессах не имеет значения для этого конкретного сценария. Каждому процессу назначается одинаковое количество виртуального адресного пространства. Размер этого пространства не зависит от объема оперативной памяти на вашем компьютере или других запущенных процессах.

То, что здесь происходит, вероятно, одно из следующих

  • Вы просто выделили слишком много памяти. Трудно сделать в 64-битном да, но возможно
  • Нет доступного непрерывного блока памяти, который имеет запрошенный размер.
2 голосов
/ 23 октября 2009

Ваш номер указывает на размер по умолчанию стека в 1 МБ (c150K x 8). Итак, если вы быстро посмотрите на ваш код (и особенно на map :: insert и не предоставляя код для «...»), вы столкнетесь с взаимодействием со stackoverflow.com:)

Возможно, вы используете его для ОС, на которой он запущен. В Windows используйте настройки компоновщика VS или используйте editbin.exe или какой-нибудь экзотический непортативный api, утроите размер стека и посмотрите, значительно ли он изменит наблюдаемый рекурсивный счет во время исключения.

1 голос
/ 23 октября 2009

Как упоминает Маджкара, пространство стека потоков имеет фиксированный размер, и вы исчерпываете его - не имеет значения, сколько у вас свободной памяти. Вам нужно переписать свой алгоритм, чтобы он был итеративным, используя stl :: stack, выделенный в куче (или какой-либо другой структуре данных), чтобы отслеживать глубину.

1 голос
/ 23 октября 2009

Возможно, ваше приложение страдает от фрагментации памяти . Возможно, имеется достаточно доступной памяти, но она может быть фрагментирована на гораздо меньшие непрерывные блоки, чем требует ваше приложение.

...