![]() |
|
![]() ![]() ![]() |
|
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
в режиме дебага когда идет запись в вектор
на функции SomeFuncPushTovec(); вылетает на
по стэку вызовов понять ничего не удалось. предполагаю, что что то связанное с ограничением на память (в е CMemoryException). почему это происходит? |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Стек вызовов в момент отлова исключения рассматривать бесполезно. Нужно ловить исключение в момент генерации.
Во первых, нужно понять какой тип исключения. Это можно увидеть (в дебаге) в Output-окне. Там должно быть написано что-то вроде First chance exception at... Далее нужно в окне Debug-Exceptions включить перехват нужных типов исключений; можно сразу группу, а не поштучно. Если тип исключения понять не получается, попробуй C++ exceptions и Run-time (не помню. точно как называются - там где Access violation и т.д.) Вот в момент генерации исключения смотри стек. Иногда бывает, что ты ловишь не первичное исключение, а "переизлученное". Тогда нужно еще поработать с окном перехвата исключений... и внимательно смотреть Output (найти самое первое исключение) -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
во время дебага нажал Ctrl + Alt +E
и поставил галочку напротив С++ Exeptions->CExeption ну и дебагер остановился на том же месте CATCH_ALL(e) тип исключения CMemoryExeption в логе дебаг окна Microsoft C++ exception: CMemoryException at memory location я так и не понял как посмотреть из какого куска кода оно пришло. |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Возможно, что-то сделано неправильно. Но бывает, и что не срабатывает.
Тогда попробуй отловить момент создания исключения CMemoryException - поставь точку прерывания в MFC-коде. -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
надо было перед дебагом.
вообщем. First-chance exception CMemoryException at memory location bgheap.c на строчке /* do the allocation */ pvBlk = _heap_alloc_dbg_impl(nSize, nBlockUse, szFileName, nLine, errno_tmp); посмотрел по стеку похоже просто не может выделить память в вектор (машина имеет 2гб. оперативной памяти заполняется полностью) хотя пробовал запускать откомпилированный экзешник на машине с 4Гб всю память не занимает, а вываливается примерно на 2Гб. Это сообщение отредактировал(а) mrgloom - 12.9.2011, 16:27 |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Похоже??? Если ты реально ждал, что тебе 2 гб в хипе выделят, тебе срочно нужен ликбез - надо книжку какую-никакую прочесть, про виндоус, про память и т.д., Рихтера, например. ![]() -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
ну я так подозреваю что 2гб это предел для приложения в х32 системе? (хотя вроде тяжелые приложения как то расширяют это дело до 3Гб).
попробую под х64. и еще как то можно оценивать полный объем памяти, который использует программа, чтобы она не падала на х32? Upd: на х64 та же история (2GB per process) или я чего то делаю не то. хотя на х64 всего 2Гб памяти так что может быть и в этом проблема. Это сообщение отредактировал(а) mrgloom - 13.9.2011, 11:28 |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
пробовал этот метод скомпилировать с флагом /LARGEADDRESSAWARE
http://msdn.microsoft.com/en-us/library/wz223b1z эффект тот же, хотя возможно из-за того, что х64 имеет 2Гб, но по идее есть еще и файл подкачки. |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
На 32-битной платформе процессу выделяется 4 гб виртуального адресного пространства. Больше не позволяет адресация. В это же адресное пространство отображаются все необходимые системные библиотеки, а также сам процесс. Сколько памяти есть физически в системе - не важно, это будет влиять только на скорость (разве что на диске не хватит места под своп или своп вообще отключен). Под хип остается то, что не занято стеком и прочими запросами на память. Причем хип может фрагментироваться. Так что рассчитывать на большой кусок не стоит.
Под 64-битной платформой памяти процессу должно выделяться по идее больше. Почему у тебя не получилось, не знаю. Разве что ты не компилировал под 64, а просто запустил 32-битное приложение. -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
нет я скомпилировал под х64(статическая линковка на выходе только 1 экзешник, флаг /LARGEADDRESSAWARE проставил насильно) (на системе х32 специально проверил экзешник не запустился) перенес на систему х64 и запустил там(только там 2Гб памяти) и начал смотреть что там происходит через vmmap примерно когда heap занимал 1.8Гб , а полный размер ~2Гб все начало свопиться и начались дикие тормоза, а потом все равно приложение вроде бы упало.
может нельзя выделять больше 2Гб непрерывной памяти? или на это нет ограничений? |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Не могу сказать. Пока с 64-битными приложениями не связывалась... Теоретически вроде не должно быть такого ограничения, но хз -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
запустил на машине х64 с 4 гб, программа отъела 4Гб и сообщила, что ей не хватает памяти.
вообщем все работает, но почему то файл подкачки она кушать не хочет. причем программа не падает, но и память не сбрасывает. т.е. она кушает много памяти на ф-ии add_many_items_to_vector() потом вылетает эксепшн на память и как дальше она себя ведёт\должна вести не очень понятно. Добавлено через 4 минуты и 15 секунд может возможно контролировать как то поведение программы на таких участках? или как то все время проверять с какой то периодичностью. что то типа
|
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Может, проще не жрать столько памяти?
![]() Я за свою довольно долгую карьеру ни разу с таким проблемами не сталкивалась... Нельзя же программировать на абстрактной машине Тьюринга. -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
заранее рассчитывалось, что приложение может есть много памяти.
аппетиты конечно сократятся, но хотелось бы уметь и обрабатывать такие ситуации нехватки памяти. |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
т.е. даже по сути вопрос сводится к тому как в программе должно обрабатываться при нехватки памяти
скажем такое while(1) { vec.push_back(item); } почитал тут http://users.msu.dubna.ru/~nefedov/c++course/p2-3.html но там про new[],но я то работаю со стандартным вектором. |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
У тебя же генерируется CMemoryException? Вот его и лови.
Хотя странно, если std::vector, там другой тип исключения; точно не помню, тоже про память. Короче, выясни тип исключения и лови, в чем проблема? Кстати, имей в виду. Вектор растет не по одному элементу а кусками. Причем, алгоритм определения размера прироста обычно довольно простой - типа удвоения текущего размера. Т.е. если тебе не хватит места всего под один элемент, вектор попытается раздуться вдвое. И может лопнуть. Далее, перевыделение памяти происходит так: выделяем новый кусок, копируем туда старые значения, освобождаем старый. В результате - память фрагментируется! Т.е. возможен случай, когда память вроде есть, на 1000 мелких кусочков. Но вот на один большой (равный в сумме 1000 мелких) - фиг вам. Короче, при больших аппетитах полагается сразу определиться с примерно нужным размером и заказать его сразу + небольшой запас, возможно. Нельзя с большим вектором работать точно также как с маленьким. -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
если есть vector<vector<point>>
и я точно не знаю размер внутренних векторов и внешнего вектора, но например хочу под это дело выделить кусок памяти 2Гб, как это можно сделать? |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Никак, разве что свой аллокатор писать.
Либо дизайн пересмотри. Например, можно сделать так: выделить большой пул для всех точек в виде vector<point>, а отдельную линию хранить как <начало-конец>. Либо как-то еще упаковать, и прописать извлечение в виде объекта. Это требует довольно много кода, но при работе с большими массивами данных обойтись стандартными контейнерами не получится. Например, у меня в программе векторные данные хранятся в виртуальной памяти (а не в хипе), в виде упакованных блоков, без всяких указателей. Для каждого слоя есть 2 параллельных пула: массив тэгов фиксированного размера (тэг - это структура, где записан тип объекта, экстент, размер, позиция во втором пуле и некоторые доп. данные). Второй пул содержит блоки разных размеров, где хранятся собственно данные (массив координат и т.д.). На оба пула сверху навернута поддержка списка свободных блоков. Все это закрыто в наборе классов, наружу торчат только ручки типа "Разместить объект", "Удалить", "Изменить". Объект извлекается в виде пары указателей (на тэг и данные), сверху навернуты объектные обертки. Причем их два типа (2 набора): "легкие" обертки, только для чтения, зато быстро создаваемые (например, прорисовка или поиск) и полновесные классы, для редактирования/создания. Смысл примерно такой: упакованные данные занимают намного меньше места, меньше страдают от фрагментации, легко сериализуются (всем куском); для чтения (рисования) достаточно inline-оберток, которые преобразуют указатели к нужному типу и ничего не стоят. А полноценный объектный доступ нужен только при редактировании отдельных объектов. Тогда точки копируются в вектора (для полилиний), модифицируются, а потом снова упаковываются. -------------------- ... |
|||
|
||||
mrgloom |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 829 Регистрация: 8.6.2011 Репутация: нет Всего: нет |
у меня проблема несколько в другом
у меня данные хранятся не в готовом для вывода виде, а в виде типа 1.есть описание объекта.(какая то фигура, например квадрат) 2.есть действия над объектом(переместить в точку, повернуть и т.д.) т.е. весь файл например состоит из N таких фигур, но с разными действиями над ними, возможны вложенности одних фигур в другие. "развернуть" все эти "заготовки" в реальные примитивы я не могу т.к. займет много памяти, приходится выцеплять частями, только те которые нужно. в памяти я храню только описание объектов+ "куда их поставить". я заранее простчитываю ограничивающие прямоугольники объектов и потом в цикле(когда надо отрисовать) накладываю на них преобразования(переместить, повернуть..) и проверяю 1. Если ограничивающий прямоугольник пересекается или попадает в текущий видимый в программе прямоугольник. 2. если размер прямоугольника достаточно большой(чтобы не выводить маленькие). вообщем проблема в том, что при каждой отрисовке гуляет размер вектора, который содержит данные для отрисовки, и его размер может меняться, в теории я на каждой итерации могу оценить его размер, но это скажется по процессору. скорее всего придется выводить "порциями", т.е. дошли до лимита скажем в 10к элементов- вывели, потом опять ищем. но как этот лимит правильно определить хз, т.е. если вообще по 1 примитиву выводить лишней памяти не надо, но будет медленно. вот код отрисовки, приходится еще выделять доп. память под временное хранилище. vec это vector<vector<vector<point>>> , он содержит vector<vector<point>> т.е. список примитивов, которе приходят из разных тредов.
Это сообщение отредактировал(а) mrgloom - 4.10.2011, 14:45 |
|||
|
||||
![]() ![]() ![]() |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |