StackOverFlowException: это ошибка программирования (рекурсия) или недостаточно максимального размера стека по умолчанию? - PullRequest
0 голосов
/ 27 января 2012

Я пытаюсь получить информацию о конфигурации виртуальной машины для виртуальной машины в VMware, используя подход SDK для веб-сервисов.Мне удалось получить информацию о конфигурации виртуальной машины из простого консольного приложения, интерфейса командной строки (Powershell) моего инструмента.Однако, когда я пытался сделать то же самое в своем пользовательском интерфейсе (MMC-Snapin), я получаю исключение StackOverflowException.Можете ли вы помочь мне или дать мне советы по устранению ошибки?

Обратите внимание, что тот же код работает с консолью / командной строкой (powershell).Не из MMC UI (я позаботился о сериализации).Это как-то связано с ограничениями стека в MMC?Я понятия не имею, как это отладить.Любые идеи / предложения действительно помогают?

Я дал код ниже.Обратите внимание, что как только я отменяю комментарий в свойстве «config» из коллекции свойств, я получаю стекопоток из оснастки MMC.

С уважением, Dreamer


В другихсловами, нужно ли увеличивать размер стека для интерфейса MMC?


Увеличение максимального размера стека потока до 8 МБ (8388608), без исключения.Но Я не доволен исправлением, как если бы большие данные поступали?

На самом деле установка его в стек размером 1 МБ работает.Поэтому, вероятно, размер стека по умолчанию для MMC низкий.Не уверен, вызывает ли увеличение до 1 МБ какие-либо побочные эффекты.Любые комментарии / мысли?

Кстати, исключение исходит от VMWARE SDK (vimservice / vimserializers / system.xml), который я не могу контролировать.

С уважением, Нареш

TraversalSpec datacenterVMTraversalSpec = new TraversalSpec();
                datacenterVMTraversalSpec.type = "Datacenter";
                datacenterVMTraversalSpec.name = "datacenterVMTraversalSpec";
                datacenterVMTraversalSpec.path = "vmFolder";
                datacenterVMTraversalSpec.skip = false;
                datacenterVMTraversalSpec.selectSet = new SelectionSpec[] { new SelectionSpec() };
                datacenterVMTraversalSpec.selectSet[0].name = "folderTraversalSpec";

                TraversalSpec folderTraversalSpec = new TraversalSpec();
                folderTraversalSpec.name = "folderTraversalSpec";
                folderTraversalSpec.type = "Folder";
                folderTraversalSpec.path = "childEntity";
                folderTraversalSpec.skip = false;
                folderTraversalSpec.selectSet = new SelectionSpec[] { new SelectionSpec(), datacenterVMTraversalSpec };
                folderTraversalSpec.selectSet[0].name = "folderTraversalSpec";

                    PropertyFilterSpec propFilterSpec = new PropertyFilterSpec();
                    propFilterSpec.propSet = new PropertySpec[] { new PropertySpec() };
                    propFilterSpec.propSet[0].all = false;
                    propFilterSpec.propSet[0].type = "VirtualMachine";
                    propFilterSpec.propSet[0].pathSet = new string[] { "name", 
                        //"config", //TODO: investigate including config is throwing stack overflow exception in MMC UI. 
                        "summary",
                        "datastore", 
                        "resourcePool" 
                    };

 propFilterSpec.objectSet = new ObjectSpec[] { new ObjectSpec() };
                propFilterSpec.objectSet[0].obj = this.ServiceUtil.GetConnection().Root;
                propFilterSpec.objectSet[0].skip = false;
                propFilterSpec.objectSet[0].selectSet = new SelectionSpec[] { folderTraversalSpec };

                VimService vimService = this.ServiceUtil.GetConnection().Service;
                ManagedObjectReference objectRef = this.ServiceUtil.GetConnection().PropCol;
                PropertyFilterSpec[] filterSpec = new PropertyFilterSpec[] { propFilterSpec };
                ObjectContent[] ocArray = vimService.RetrieveProperties(objectRef, filterSpec);

С уважением, Мечтатель

Ответы [ 2 ]

1 голос
/ 07 декабря 2014

По техническим причинам объем стекового пространства фиксирован. Это означает, что рекурсивные алгоритмы с большим объемом ОЗУ находятся в беде: всегда возможно, что некоторые входные данные превысят пороговое значение, и программа потерпит крах, несмотря на то, что еще остается много свободной ОЗУ.

В Windows память для стека зарезервирована , но обычно не commit (кроме .NET). Это означает, что если вашей программе требуется большой стек размером 100 МБ, используется только адресное пространство. Другие программы могут по-прежнему использовать тот же объем ОЗУ, что и до того, как вы заявили, что можете использовать до 100 МБ стека.

В .NET, поскольку пространство стека выделено , общий объем памяти, который могут выделить другие программы, в этом случае уменьшается на 100 МБ, но физическая ОЗУ фактически не выделяется до тех пор, пока ваш алгоритм не станет подлинным это нужно.

Таким образом, увеличение размера стека не так плохо, как вы думаете, особенно если вы не программируете в .NET.

Я столкнулся с ограничением стека алгоритма. К сожалению, наш алгоритм был частью библиотеки. Не желая требовать, чтобы наши вызывающие стороны запускали свои потоки с большим стеком, мы переписали алгоритм для использования явного стека в цикле вместо рекурсии. Это сделало алгоритм медленнее и сложнее для понимания. Это также сделало отладку почти невозможной. Но он сделал свою работу.

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

1 голос
/ 27 января 2012

Самый простой способ получить исключение переполнения стека - бесконечная рекурсия. Это было бы первое, что я искал. Есть ли у вас трассировка стека с вашим исключением? Это немедленно сообщит вам, если это так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...