Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
Алексей89
32 / 32 / 4
Регистрация: 19.02.2013
Сообщений: 118
1

Выделение памяти для непрямоугольного массива

13.12.2014, 21:25. Просмотров 915. Ответов 18
Метки нет (Все метки)

Возник вопрос:
У меня в любительской прожке. Для ускорения расчётов формируется два массива поскольку массивы непрямоугольные , для их выделения использованы new, в частности и во вложенных циклах. Для экономии памяти второй массив организован таким образом, что не содержит повторяющихся фрагментов, но так получилось, что оператор new вызывается помногу раз для одних и тех же координат. Переделывать программу, которая нужна для того чтобы сделать расчёты пару раз, выглядит затратным по времени, но риск получить неверные результаты сводит на нет всю инициативу. Поэтому у меня возник простой вопрос:

Если при выделении памяти под массив, new используется несколько раз для одних и тех же координат (итераторов в цикле) чем это чревато?
Имеет ли место утечка памяти?
Всё работает стабильно только на моём компьютере, или по тому что так должно быть?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.12.2014, 21:25
Ответы с готовыми решениями:

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

Выделение памяти для массива
Пишу такой код: int main() { int* arr1 = new int; } Всё норм. ...

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

Выделение памяти для массива
верно ли выделил память для массива если нет поправьте, заранее спасибо) class...

Выделение памяти для двумерного массива
Обьясните что означает double** A = new double*, A = new...

18
Velesthau
524 / 426 / 159
Регистрация: 25.11.2014
Сообщений: 1,662
13.12.2014, 21:28 2
Цитата Сообщение от Алексей89 Посмотреть сообщение
new вызывается помногу раз для одних и тех же координат
Что значит "new для координат"?
0
Шенец Николай
10 / 10 / 5
Регистрация: 10.12.2014
Сообщений: 60
13.12.2014, 21:36 3
Лучший ответ Сообщение было отмечено Алексей89 как решение

Решение

Если память несколько раз выделяется для одних и тех же элементов многомерных массивов, то да, это чревато утечкой памяти и не только. Такой код - "кривой". Всякий раз, когда вы хотите изменить длину массива или перевыделить под него память, надо либо сперва освобождать и потом выделять новую, либо воспользоваться функцией realloc. Первый вариант предпочтительнее, т.к. поведение функции realloc, вообще говоря, не предсказуемо.
1
Алексей89
32 / 32 / 4
Регистрация: 19.02.2013
Сообщений: 118
13.12.2014, 22:01  [ТС] 4
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CP32OctnK=new unsigned int***[10-4+1];  //Обьявление L-измерения для CP32OctnK
KvectOct=new unsigned int**[10-4+1];    //Обьявление L-измерения для KvectOct
for(L=4;L<=10;L++){             //Цикл итераций L
 
 CP32OctnK[L-4]=new unsigned int**[r];  //Обьявление CS-измерения для CP32OctnK.
 KvectOct[L-4]=new unsigned int*[(29+7)-(23+1)+1];      //Обьявление "CS-LstDgt"-измерения. 
 for(CS=23;CS<=29;CS++ ){
  CP32OctnK[L-4][CS-23]=new unsigned int*[r];           //Обьявление LstDgt-измерения для CP32OctnK.       
  for(LstDgt=1;LstDgt<R;LstDgt++){//Цикл Итераций LstDgt
...
   CP32OctnK[L-4][CS-23][LstDgt-1]=new unsigned int[nK];
   KvectOct[L-4][CS-LstDgt-16]=new unsigned int[nK+1];                  //Выделение памяти для KvectOct-массива
  
...  
  }
 }
}
Не вдаваясь в подробности, нужно два массива CP32OctnK и KvectOct. У KvectOct на 1 измерение меньше но память для него перевыделяется во вложенном цикле (в среднем около 200 раз для каждого из "родительских" (или как их правильно назвать..) измерений). Вот я и интересуюсь:
память выделенная ранее для этих координат помечается как свободная или остаётся занятой?
при обращении к массиву KvectOct актуальным будет то последнее измерение, память под которое была выделена последней или нет? (в моём случае раз за разом, памяти выделяется одинаковое количество и она инициализируется одинаковыми значениями)
0
ValeryS
Модератор
7277 / 5530 / 693
Регистрация: 14.02.2011
Сообщений: 18,734
13.12.2014, 22:07 5
Лучший ответ Сообщение было отмечено Алексей89 как решение

Решение

Цитата Сообщение от Алексей89 Посмотреть сообщение
память выделенная ранее для этих координат помечается как свободная или остаётся занятой?
память помечается свободной когда вызывается delete (delete[]) коих я у тебя не вижу
если так нужно изменения размеров памяти используй vector
0
Алексей89
32 / 32 / 4
Регистрация: 19.02.2013
Сообщений: 118
13.12.2014, 22:08  [ТС] 6
Если память несколько раз выделяется для одних и тех же элементов многомерных массивов, то да, это чревато утечкой памяти и не только. Такой код - "кривой". Всякий раз, когда вы хотите изменить длину массива или перевыделить под него память, надо либо сперва освобождать и потом выделять новую, либо воспользоваться функцией realloc. Первый вариант предпочтительнее, т.к. поведение функции realloc, вообще говоря, не предсказуемо.
Ответ понятен, спасибо, я уже понял что код переделаю, только не решил ещё в ближайшее время, или когда-нибудь потом.
Массивы у меня не динамические, (они только хранят опорные значения функций) они формируется при старте вычислений и удаляются после окончания. Пока всё считает нормально, я главным образом пытаюсь понять считать будет всегда нормально, или мне пока просто везёт?
0
Шенец Николай
10 / 10 / 5
Регистрация: 10.12.2014
Сообщений: 60
13.12.2014, 22:12 7
Лучший ответ Сообщение было отмечено Алексей89 как решение

Решение

1. Чему равно r? (см строку 5), R =? nK =?

Если эти величины согласованы (это тут самое важное!!!), то все в этом коде нормально. Каждый вложенный цикл выделяет память под элементы, для которых память еще выделена не была. Пересечений нет. Возможно, есть участки, для которых память вообще не выделена - это все опять же в согласованности размерностей.

Пока вы память не освободите сами, то она будет считаться занятой. Автоматического сборщика мусора тут нет.
1
ValeryS
Модератор
7277 / 5530 / 693
Регистрация: 14.02.2011
Сообщений: 18,734
13.12.2014, 22:14 8
Цитата Сообщение от Шенец Николай Посмотреть сообщение
либо воспользоваться функцией realloc.
это для new штоли
Цитата Сообщение от Шенец Николай Посмотреть сообщение
т.к. поведение функции realloc, вообще говоря, не предсказуемо.
кому не предсказуемо?
Цитата Сообщение от Шенец Николай Посмотреть сообщение
надо либо сперва освобождать и потом выделять новую,
вот примерно так realloc и делает
только последовательность другая, правильная
выделили новый участок памяти
скопировали из старого в новый значения
удалили старую память
вернули указатель на новую
и что здесь непредсказуемого?
разумеется работает с памятью выделенной malloc
0
Croessmah
++Ͻ
14634 / 8381 / 1584
Регистрация: 27.09.2012
Сообщений: 20,602
Записей в блоге: 2
Завершенные тесты: 1
13.12.2014, 22:19 9
Используйте std::vector ну или умные указатели
1
Шенец Николай
10 / 10 / 5
Регистрация: 10.12.2014
Сообщений: 60
13.12.2014, 22:30 10
ValeryS, если вы не читали описание функции realloc от самих разработчиков, то почитайте - советую. Она не всегда может выделить память, когда это надо, хотя и про пару new-delete тоже самое можно сказать, но последний вариант работает стабильнее (это из личного опыта), 100% пруфа нет, и я на него не претендую. И стеб не уместен, ибо нормальный человек понимает, что я имел в виду.

Да и malloc-realloc - это C, а в С++ стандартом принято использовать new-delete.
0
Алексей89
32 / 32 / 4
Регистрация: 19.02.2013
Сообщений: 118
13.12.2014, 22:35  [ТС] 11
1. Чему равно r? (см строку 5), R =? nK =?
r=7, но это неважно эти строки я выдрал из проекта более чем в 400 строк, и они все взаимосвязаны.
Проблема же вот в чём:
Массив CP32OctnK содержит 4 измерения (L, CS, LstDgt, nK)
Массив KvectOct содержит 3 измерения (L, CS-LstDgt, nK), причём "-" это именно минус стало быть, память для nK-измерения выделяется во вложенном цикле с итератором LstDgt. Таким образом, для массива KvectOct для последнего измерения память выделяется вместо (от 7-7 до 7+7)=15 раз, целых 7*7=49 раз. а в nK-измерении в среднем по 200 значений. Даже с позиции утечки памяти для средней машины не сильно накладно, да и при повторных выделениях памяти инициализируюься те же самые значения что и в альтернативных четвёртых измерениях =D(звучит как SciFi), единственное чего я опасаюсь, что из-за некорректного использования new в один прекрасный момент в одной ячейке окажется вообще какое-то левое значение.
В принципе я уже понял, что любителю, при желании схалтурить искать поддержки у профессионалов глупо как-то, но за советы спасибо)
0
Шенец Николай
10 / 10 / 5
Регистрация: 10.12.2014
Сообщений: 60
13.12.2014, 22:41 12
Лучший ответ Сообщение было отмечено Алексей89 как решение

Решение

Ага, вижу, понял. Строку 12 надо поместить на уровень выше и выделять память только во внешнем цикле для массива KvectOct. Там явно пересечения, не заметил сразу. Да, это чревато тем, что куча будет испорчена.
1
ValeryS
Модератор
7277 / 5530 / 693
Регистрация: 14.02.2011
Сообщений: 18,734
13.12.2014, 22:53 13
Цитата Сообщение от Шенец Николай Посмотреть сообщение
а в С++ стандартом принято использовать new-delete.
ссылку плиз
что нельзя пользоваться malloc в С++?
Почему? Религия не позволяет?
разница в том что new выделяет память и вызывает конструктор, в случае неудачи кидает исключение
а malloc просто выделяет сырую память и в случае неудачи вернет NULL
да и еще есть отличие new не всегда выделяет память есть такой Placement new
Цитата Сообщение от Шенец Николай Посмотреть сообщение
если вы не читали описание функции realloc от самих разработчиков, то почитайте - советую.
разработчиков чего? 100500 платформ на которых работают плюсы и у всех разные менеджеры
да дизасемблировал я её не раз начиная с винды и кончая микроконтроллерами
вся сложность что если памяти не хватит то исключения не получишь получишь NULL и думай что с ним делать
но в большинстве случаев достаточно отрапортовать "Не хватает памяти" и завершить программу
1
Алексей89
32 / 32 / 4
Регистрация: 19.02.2013
Сообщений: 118
13.12.2014, 22:55  [ТС] 14
Ага, вижу, понял. Строку 12 надо поместить на уровень выше и выделять память только во внешнем цикле для массива KvectOct. Там явно пересечения, не заметил сразу. Да, это чревато тем, что куча будет испорчена.
Проблема в том, что длина nK-измерения вычисляется для каждого случая (поэтому массив и непрямоугольный) во внешнем цикле длина nK измерения для текущих координат ещё не известна. Очевидно мне придётся вводить учёт уже записанных значений, я этим уже занимаюсь. Однако, раз уж зашёл разговор, могу я узнать, чем грозит "порча кучи"?
0
ValeryS
Модератор
7277 / 5530 / 693
Регистрация: 14.02.2011
Сообщений: 18,734
13.12.2014, 23:06 15
Лучший ответ Сообщение было отмечено Алексей89 как решение

Решение

Цитата Сообщение от Алексей89 Посмотреть сообщение
Проблема в том, что длина nK-измерения вычисляется для каждого случая (поэтому массив и непрямоугольный) во внешнем цикле длина nK измерения для текущих координат ещё не известна.
а что мешает выделить по максимуму а потом воспользоваться Placement new
в https://ru.wikipedia.org/wiki/New_(C%2B%2B) есть пример
или создать свой тип данных

Добавлено через 4 минуты
вот еще
http://habrahabr.ru/post/185662/
1
Шенец Николай
10 / 10 / 5
Регистрация: 10.12.2014
Сообщений: 60
14.12.2014, 00:12 16
ValeryS, ругаться не хочу, тут форум не для этого. Согласен, платформ куча, если говорить о realloc, то я имел в виду стандарт ANSI C, можно и в MSDN найти достаточно инфы о ней, не обязательно для этого дизассемблировать ее.
Я не сказал, что С++ запрещает использование С-функций, наоборот, я сам предложил, как вариант, ей воспользоваться. Но если уж писать на чистом С++, то надо использовать new-delete, об этом писал Страуструп в своей знаменитой книге, об этом же сказано и в официальном документе. Если интересуетесь - сами найдите и почитайте. Надеюсь, этот неуместный спор закрыт. И да, само поведение new диктует приоритет в его сторону, т.к. вы сами можете переписать код обработчика исключения в случае нехватки памяти - это гораздо удобнее.

Добавлено через 5 минут
Алексей89, порча кучи может привести к разным результатам. В моей практике было, как минимум, 2 ситуации: в одном случае это был просто Run-time error, в другом - портились данные, и я очень долго вылавливал, в чем же проблема в коде.
1
Алексей89
32 / 32 / 4
Регистрация: 19.02.2013
Сообщений: 118
14.12.2014, 18:18  [ТС] 17
Вопрос решён.
Для этого мне понадобился массив на 13 булевых флажков, которыми помечается запись по CS-LstDgt координате.
Это позволило также ещё и не производить лишних вычислений.
Placement new на досуге обязательно разберусь как работает.
Всем большое спасибо за советы.
Тема закрыта.
0
ValeryS
Модератор
7277 / 5530 / 693
Регистрация: 14.02.2011
Сообщений: 18,734
14.12.2014, 20:22 18
Цитата Сообщение от Алексей89 Посмотреть сообщение
Placement new на досуге обязательно разберусь как работает.
Да очень просто
Хотя разобраться тоже не мешает
выделяется память, а уж как вопрос последний
C++
1
2
3
char a[1024];
char a* =new char[1024]; 
char a*=malloc(sizeof(char)*1024);
а потом включаем Placement new
извини, не знаю твоей задачи, посему домысливаю, типа начиная с трех
пишем типа
C++
1
MyStruct* ms=new (a+3)myStruct[3];
потом вдруг выяснили что три нам мало нужно пять
пишем
C++
1
MyStruct* ms=new (a+3)myStruct[5];
память переписывается с нуля,появляются новые компоненты, разумеется вопрос о сохранении данных, и размере массива структур, лежит на совести разработчика
Но насколько я понял это тебе и нужно
Выдели максимум памяти, а потом работаю как с ней хочу
Этакий свой менеджер памяти

Добавлено через 28 минут

Не по теме:

Цитата Сообщение от Алексей89 Посмотреть сообщение
Вопрос решён.
Да ну:)
Дай Бог тебе здоровья и счастья
но Вопрос решен, в данной конкретной задаче,
В принципе вопрос не решен:)
и не мои подсказки не Шенец Николай, к решению не приблизили, ибо как мы с ним не раздраивались, ни один из нас не предложил
Цитата Сообщение от Алексей89 Посмотреть сообщение
понадобился массив на 13 булевых флажков,
ибо
извини предложу аналогию
падает мост
техник предлагает как усилить балку, чтобы она не падала(твой уровень)
инженер как рассчитать нагрузку чтобы балка не падала, то бишь новый мост (это уровень мой и Шенец Николай), не бери в голову что мы здесь с ним оппонируем, нормальная ситуация среди творческих людей :)
и третий уровень Академика( дай Бог мне дорасти до этого уровня), который говорит:"А нахрена вам мост?Может засандалим здесь телепортацию?"
Я конечно утрирую, но я думаю что Шенец Николай хочет дойти до такой категории,Я то железно:)
ну и дальше, мечты в слух, "Мы все учились по немногу, чему нибудь и как нибудь"(с) Пушкин
Мечтаю встретится с людьми которые хотят "Чего то странного" (с) Стругатские

Извини поток мыслей, но смысл простой
Учись и никто тебя не остановит, знания-сила, особенно когда знания пропущены через себя, и даже говорят так нельзя, проверь а может можно:)
я по образованию электронщик и за закон Ома "харю порву", но не потому что Ом крутой, а потому что его закон действует

1
Шенец Николай
10 / 10 / 5
Регистрация: 10.12.2014
Сообщений: 60
14.12.2014, 20:51 19
ValeryS, отличные мысли "не по теме"
0
14.12.2014, 20:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.12.2014, 20:51

Динамическое выделение памяти для массива
Не могу разобраться, почему программа вызывает точку остановы после выбора...

Динамическое выделение памяти для массива
Кто может помочь решить задачу. Для заданного двумерного массива из n строк и...

Выделение динамической памяти для двумерного массива.
#include &lt;iostream&gt; int main() { setlocale( LC_ALL,&quot;Russian&quot; ); int...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru