Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Закрытая тема
Ваша тема закрыта, почему это могло произойти? Возможно,
Нет наработок или кода, если нужно готовое решение - создайте тему в разделе Фриланс и оплатите работу.
Название темы включает слова - "Помогите", "Нужна помощь", "Срочно", "Пожалуйста".
Название темы слишком короткое или не отражает сути вашего вопроса.
Тема исчерпала себя, помните, один вопрос - одна тема
Прочитайте правила и заново правильно создайте тему.
 
Опции темы Поиск в этой теме
Старый 25.04.2009, 15:48   #11
Андрей Куб
Пользователь
 
Регистрация: 13.05.2008
Сообщений: 12
По умолчанию

Цитата:
Сообщение от Jeni Посмотреть сообщение
Ну и где это было показано в коде в первом сообщении?
Я ведь написал что весь модуль не вместился в лимит 5000 знаков,оставил только те части где могла быть ошибка, и приложил архив с исходником.
Да и собственно говоря тип Chelovek вроде как к стандартным не относится, по этому то что он описан - можно было и догадаться =)
Андрей Куб вне форума
Старый 26.04.2009, 07:20   #12
Скандербег
Форумчанин
 
Регистрация: 04.04.2009
Сообщений: 438
По умолчанию

Цитата:
Сообщение от Андрей Куб Посмотреть сообщение
Вы такой классный, советуете почистить результирующий массив?
А лучше вообще не исправлять ошибки в своих программах,правда?
Иронию вашу понимаю. Но если приведенный код вы сами писали, тогда вы не знаете что делаете, если же кто-то другой, то показываю на пальцах.
При входе в процедуру Generate есть строка:
setlength(ochered,36000);
далее по тексту встречается такая конструкция:
setlength(Ochered,t);
Это разве я писал?
При каждом следующем нажатии на кнопку SetLength вызывается снова и снова.
А теперь объясните себе зачем здесь применяется процедура SetLength и что она делает. Может тогда поймете, что ирония ваша была не уместна

Цитата:
Сообщение от Андрей Куб Посмотреть сообщение
тыркать кнопку 10 раз нужно хотябы потому что 10 раз могут меняться начальные данные, и что теперь прогу перезагружать если хочешь промоделировать заново?
Ради бога, вызывайте процедуру сколько угодно (это было простым моим недоумением, объяснили, и ладно), а массив, который перестраивается при каждом вызове процедуры два раза уже сложно назвать результирующим. И если не очищать память перед переразмещением массива, то ошибка будет в программе всегда, только проявляться она может по разному. На моем компе она, например, выглядела как "Access violation...", а не ошибкой переполнения стека.

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

Последний раз редактировалось Скандербег; 26.04.2009 в 07:52.
Скандербег вне форума
Старый 26.04.2009, 23:33   #13
Андрей Куб
Пользователь
 
Регистрация: 13.05.2008
Сообщений: 12
По умолчанию

Цитата:
Сообщение от Скандербег Посмотреть сообщение
Иронию вашу понимаю. Но если приведенный код вы сами писали, тогда вы не знаете что делаете, если же кто-то другой, то показываю на пальцах.
При входе в процедуру Generate есть строка:
setlength(ochered,36000);
далее по тексту встречается такая конструкция:
setlength(Ochered,t);
Это разве я писал?
При каждом следующем нажатии на кнопку SetLength вызывается снова и снова.
А теперь объясните себе зачем здесь применяется процедура SetLength и что она делает. Может тогда поймете, что ирония ваша была не уместна
Моя ирония вполне уместна.
setlength(ochered,36000)< точнее даже будет не 36000 а допустим переменная time, time -это килличество "секунд" рабочего дня которого я моделирую,Я предполагаю самый худший вариант что каждую секунду кто-то приходит, Конечно это слишком избыточное предположение но всёже я решил сделать так.

Далее у меня идёт цикл который рассчитывает реальное время прихода людей и другие вещи, связанные с моделированием. переменная t после выполнения данного цикла будет содержать количество людей которые успели прийти за рабочий день time.

Код:
While (x<time1)  do begin
ochered[t][1]:=RandomRange(IntervalFrom,IntervalTo);
ochered[t][2]:=RandomRange(ZaprosFrom,ZaprosTo);
ochered[t][3]:=RandomRange(PrintZFrom,PrintZTo);
ochered[t][4]:=Search;
ochered[t][5]:=RandomRange(ChooseFrom,ChooseTo);
ochered[t][6]:=RandomRange(PrintFrom,PrintTo);
ochered[t][7]:=RandomRange(accurFrom,accurTo);
ochered[t][8]:=RandomRange(BookFrom,BookTo);
/////////////////////Общее время облуживание у оператора/////////////////////
ochered[t][9]:=ochered[t][2]+ochered[t][3]+ochered[t][4]+ochered[t][5]+
ochered[t][6]+ochered[t][7];
/////////////////////Общее время облуживание у оператора/////////////////////
x:=x+ochered[t][1];
inc(t);
Собственно делая setlength(ochered,t) я отсекаю ненужные пустые ячейки
и использую length(Ochered) уже как собственно количество людей.

конечно, я бы мог сделать в цикле setlength(ochered,Length(ochered)+1 )
вместо накапливания t но на мой взгляд этот варриант хуже, и на сколько я помню, он так-же вылетает.

так что, собственно ,если вы мне предлагаете сделать
Цитата:
ochered := nil; //а здесь тем более, раз перестраиваем динамический массив
перед setlength(Ochered,t); я думаю вы сами догадываетесь что произойдет с данными в массиве.


Цитата:
Ради бога, вызывайте процедуру сколько угодно (это было простым моим недоумением, объяснили, и ладно), а массив, который перестраивается при каждом вызове процедуры два раза уже сложно назвать результирующим. И если не очищать память перед переразмещением массива, то ошибка будет в программе всегда, только проявляться она может по разному. На моем компе она, например, выглядела как "Access violation...", а не ошибкой переполнения стека.

Если же вам действительно нужен "результирующий" массив и все же очень хочется, чтобы ошибка не появлялась, то SetLength надо вызвать один раз (36000 - константа) и не в этой процедуре. Как только вы это сделаете, от надоевшей вам ошибки и следа не останется (придут другие ).
"Access violation..." у меня выдаёт программа а стак оверлор оччент редко когда выдаёт компилятор но не показывает касячную строчку.

Цитата:
а массив, который перестраивается при каждом вызове процедуры два раза уже сложно назвать результирующим
Знаете, может конечно я чего-то непонимаю, но динамический массив на то и есть динамический чтобы перестраиваться хоть милион раз за процедуру, у него назначение такое, если что =)

Ради прикола, напишите программу, наховите её hello, World обязательно.
И пусть она вам продемонстрирует уличную магию =)
procedure VrotMneNogi;
var
a:array of integer;
x:integer;
begin
for x:=1 to 999 do begin
setlength(a,RandomRange(1,999999));
end;
end;

Не обижайтесь , но вы не правы, и кстати говоря, зря вы сомневаетесь что я понимаю что делаю =)

Последний раз редактировалось Андрей Куб; 26.04.2009 в 23:59.
Андрей Куб вне форума
Старый 27.04.2009, 06:00   #14
qpokyc
Форумчанин
 
Аватар для qpokyc
 
Регистрация: 07.04.2009
Сообщений: 117
По умолчанию

Эх, а ведь когда-то я сам был таким
Цитата:
я уж извиняюсь но где ты нашел большое число ВХОДНЫХ параметров у функций?
Это я тебе сообщил для просветления в причинах ошибки. Извини, но твою прогу просмотрел мельком (стошнило на монитор, не помню на какой строчке). Очень восхищаюсь теми, у кого нервы оказались крепче
Цитата:
Времена когда память переполнялась из-за 20 локальных переменных прошли лет 20 назад уже =)
Тоже полезная историческая справка, без тебя бы ни как не догадался. Но с чего ты взял, что я говорил про "память"?
Цитата:
Про стек я уже сказал
Оно понятно - ударим железом по лени! Можно глупый вопрос: почему хорактеристики по типу ImageBase и StackSize не установлены по дефолту в их критические значения? (Если верить тебе - чтобы багов было больше!)
Цитата:
Никаких объектов я не создаю, а переменные все обнуляются;
Не создаешь, но используешь! Ну это ладно - не создаешь, так не создаешь...
Цитата:
Про насмешку про то "как правильно оформлять код" я промолчу, но если вам по делу сказать было нечего не стоило ничего отвечать
Я со своим учителем тоже спорил с пеной у рта постоянно - стоит или не стоит оформлять код как это положено. Жизнь показала, что стоит...

То что ты здесь выложил, если не изменяет память называется "приступом гениальности" (это когда стандартную задачу решают через известное место). У меня своих сорсов целая пачка, и все ждут отладки и тестирования, а потом снова отладки и т.д. Словом, если тебе не пригодились мои советы (а их, обычно, не любят - любят тока готовые решения) - мог бы и сам промолчать, я здесь больше вообще постить не собирался.

PS: SetLength выделяет/освобождает память по дин. массивы (ты бы исчо $EFFFFFFF элементов задал). Кстати, если ты думаешь, что max памяти под образ = вся память системы (не считая ОСь, включая подкачку), то ты сильно ошибаешся . Слушал бы людей:
Цитата:
При каждом следующем нажатии на кнопку SetLength вызывается снова и снова.
И не огрызался...
Copyright © qpokyc (qpy[the dog]bk.ru), 2008-2009 г.
qpokyc вне форума
Старый 27.04.2009, 09:29   #15
Скандербег
Форумчанин
 
Регистрация: 04.04.2009
Сообщений: 438
По умолчанию

Цитата:
Сообщение от Андрей Куб Посмотреть сообщение
Не обижайтесь , но вы не правы, и кстати говоря, зря вы сомневаетесь что я понимаю что делаю =)
Ну, что вы, я не обижаюсь. Дело обычное - спор двух "гуру". А вот сомневаюсь я не зря.
Тонкость работы процедуры SetLength в том, что при повторном распределении памяти под один и тот же массив используется уже ДРУГОЙ блок.
И никакой гарантии, что ячейки памяти, которые использовались в прежнем массиве будут использованы в новом блоке нет.
К тому же, при выделении другого блока Delphi НЕ КОПИРУЕТ в него данные из прежнего.
Поэтому когда вы предполагаете, что отсекаете ненужные ячейки ("я отсекаю ненужные пустые ячейки"), а Delphi благородно переместит данные из одного блока в другой, то в этом то и есть непонимания процесса.
Да, при выполнении вашей программы может происходить "удачное" повторное распределение блока, который будет практически совпадать с прежним, но как только произойдет "не удачное", с точки зрения программы, распределение, то в этом случае и может появится ошибка, т.к. конструкция, например, ochered[t] будет обращаться к несуществующей области памяти.
Оттого и ошибка блуждающая.

Я могу понять доводы размещения в памяти 720 000 элементов Integer (хотя всецело присоединяюсь к qpokyc в части его высказывания: "ты бы исчо $EFFFFFFF элементов задал") - это не профессионально, но допустимо.
Но я никак не могу понять, почему вы не хотите проверить мои слова на практике.
В программе я сделал так:
- закомментировал в процедуре Generate все вызовы SetLength(ochered, ), затем создал массив один раз:
Код:
procedure TForm5.Button1Click(Sender: TObject);
begin
  if Ochered = nil then
    setlength(Ochered,36000);
  Generate;
end;
Это лишь пример и не в стиле профи, но в вашем модуле больше негде было, а вы можете один раз распределить массив при создании формы, например, или еще где - мест много.
После этого несколько раз перезапуская программу нажимал кнопку по 10-30 раз - ошибки не было ни разу.

Использовать length(Ochered) - это хорошо, но уж если массив создан с избыточностью, то не надо его перераспределять, а можно применять переменные (t, time1, к примеру) для определения количества значащих элементов в каждый момент времени или как-нибудь по-другому, варинатов тоже тьма.

Цитата:
Сообщение от Андрей Куб Посмотреть сообщение
но динамический массив на то и есть динамический чтобы перестраиваться хоть милион раз за процедуру, у него назначение такое
А с этим никто и не спорит. Только работать с дин.массивом надо уметь корректно, И все дела.

----
Без обиды, но не могу не поддержать qpokyc в части "правильности" оформления текста программы.
Ну, поймите вы, такой текст как у вас будет малочтабельным и для вас самого через пару месяцев.
Не говоря уж об элементаром уважении к тем, кто этот текст пытается разобрать.
В нормально оформленном коде и разбираться приятно - чувствуется единомышленник. Такого при прочих равных условиях уже не хочется посылать куда подальше.
Конечно, это лишь совет и вы, естественно, вольны следовать ему или плюнуть на него.
Скандербег вне форума
Старый 27.04.2009, 14:46   #16
Андрей Куб
Пользователь
 
Регистрация: 13.05.2008
Сообщений: 12
По умолчанию

Скандербег, спасибо большое, помогло.

Я дествительно не правильно понимал работу дин. массива. еще раз сенкс.




Цитата:
То что ты здесь выложил, если не изменяет память называется "приступом гениальности" (это когда стандартную задачу решают через известное место). У меня своих сорсов целая пачка, и все ждут отладки и тестирования, а потом снова отладки и т.д. Словом, если тебе не пригодились мои советы (а их, обычно, не любят - любят тока готовые решения) - мог бы и сам промолчать, я здесь больше вообще постить не собирался.
Через жопу говоришь? чтобы не быть голословным предложи своё решение моей "стандартной" задани не через "жопу"
А вообще, если бы в тебе было стока же знаний скока пафоса наверное ты бы был хорошим спецом) А не человеком который чёто где-то слышал но знать толком не знает, по этому отделывается фразами "мне лень" "меня стошнило" и тд...
Единственное в чем я с тобой согласен это в том что
Цитата:
я здесь больше вообще постить не собирался
Привет учителю, кстати, код действительно нужно оформлять, просто сейчас у меня другие цели, а конкретно - побыстрее получить готовую задачу, а в своих каракулях я разбираюсь =)
Андрей Куб вне форума
Старый 27.04.2009, 23:44   #17
Jeni
Форумчанин
 
Регистрация: 31.05.2007
Сообщений: 486
По умолчанию

Возможно я влезаю не по теме, но очень уж хочется решить этот вопрос раз и навсегда.
Цитата:
Сообщение от Скандербег Посмотреть сообщение
Тонкость работы процедуры SetLength в том, что при повторном распределении памяти под один и тот же массив используется уже ДРУГОЙ блок... К тому же, при выделении другого блока Delphi НЕ КОПИРУЕТ в него данные из прежнего.
Недавно я уже интересовался здесь подобным вопросом и меня клятвенно заверили, что при задании новой длины массива в любом случае происходит копирование старых данных. Для меня принципиально важно было, чтобы данные не терялись - программа довольно ответственная.
Так что же всё-таки правильно: может происходить потеря данных при усечении/расширении массива или нет?
Jeni вне форума
Старый 28.04.2009, 00:46   #18
Роман Радер
Форумчанин
 
Аватар для Роман Радер
 
Регистрация: 16.12.2006
Сообщений: 859
По умолчанию

Код:
может происходить потеря данных при усечении/расширении массива или нет?
я всегда использую setlength для удаления последнего элемента и НИКОГДА не было потерь данных. С чего вы взяли вообще что меняется дислокация элементов? просто "исчезает" последний. так что никакого копирования, все просто остается на своих местах.
а вот если сначала на один уменьшить, а потом обратно прибавить - нельзя быть таким увереным про восстановление данных.
Роман Радер вне форума
Старый 28.04.2009, 02:16   #19
Jeni
Форумчанин
 
Регистрация: 31.05.2007
Сообщений: 486
По умолчанию

Цитата:
Сообщение от Роман Радер Посмотреть сообщение
я всегда использую setlength для удаления последнего элемента и НИКОГДА не было потерь данных. С чего вы взяли вообще что меняется дислокация элементов? просто "исчезает" последний. так что никакого копирования, все просто остается на своих местах.
Насчет уменьшения размера массива у меня никогда и не было сомнений - в этом случае просто уменьшается память, отведенная под массив (т.е. меняется только одно значение в служебных данных) и, соответственно, ни о каком перераспределении памяти и ни о каких потерях данных не может быть и речи.

Цитата:
Сообщение от Роман Радер Посмотреть сообщение
а вот если сначала на один уменьшить, а потом обратно прибавить - нельзя быть таким увереным про восстановление данных.
Вот об этом и речь. Точнее - вопрос. Если убавить на один элемент (или несколько), а потом добавить на столько же, то никаких вопросов - массив останется там же (если конечно между удалением/увеличением не будет других операций по распределению памяти кучи). А вот если увеличивать на значительную величину, да еще вперемешку с другими операциями? Массив ведь не может быть "рваным". Если для его переразмещения не хватит памяти на прежнем месте, то менеджер кучи выделит новый кусок - но всегда ли будут скопированы в новое место старые данные?

Последний раз редактировалось Jeni; 28.04.2009 в 02:18.
Jeni вне форума
Старый 28.04.2009, 06:54   #20
qpokyc
Форумчанин
 
Аватар для qpokyc
 
Регистрация: 07.04.2009
Сообщений: 117
По умолчанию

Цитата:
Возможно я влезаю не по теме, но очень уж хочется решить этот вопрос раз и навсегда.
Навсегда и для всего вы не решите, но по части Delphi7 попытаюсь. По части альтернативных сред - пусть топикстартер сам зырит. А зырить надо в исходники стандартных библиотек.

Как SetLength работает с обычной строкой понятно каждому:
1) Нулевой елемент := длинна строки
2) Память НЕ перераспределяется
И исходник сей процедуры тому подтверждение:
Код:
procedure       _SetLength(s: PShortString; newLength: Byte);
begin
  Byte(s^[0]) := newLength;   // should also fill new space
end;
Модуль System не захотел сам выдавать свои "секреты", пришлось воспользоваться Find.

Судя по заголовку и коменту, эта процедура работает с нуль-терминированной строкой (по идее, может работать с любым дин. массивом, по крайней мере - ничего другого в этом духе я в модуле не нашел)
Код:
procedure       _LStrSetLength{ var str: AnsiString; newLength: Integer};
asm
        { ->    EAX     Pointer to str  }
        {       EDX new length  }

        PUSH    EBX
        PUSH    ESI
        PUSH    EDI
        MOV     EBX,EAX
        MOV     ESI,EDX
        XOR     EDI,EDI

        TEST    EDX,EDX
        JLE     @@setString

        MOV     EAX,[EBX]
        TEST    EAX,EAX
        JE      @@copyString

        CMP     [EAX-skew].StrRec.refCnt,1
        JNE     @@copyString

        SUB     EAX,rOff
        ADD     EDX,rOff+1
        PUSH    EAX
        MOV     EAX,ESP
        CALL    _ReallocMem
        POP     EAX
        ADD     EAX,rOff
        MOV     [EBX],EAX
        MOV     [EAX-skew].StrRec.length,ESI
        MOV     BYTE PTR [EAX+ESI],0
        JMP     @@exit

@@copyString:
        MOV     EAX,EDX
        CALL    _NewAnsiString
        MOV     EDI,EAX

        MOV     EAX,[EBX]
        TEST    EAX,EAX
        JE      @@setString

        MOV     EDX,EDI
        MOV     ECX,[EAX-skew].StrRec.length
        CMP     ECX,ESI
        JL      @@moveString
        MOV     ECX,ESI

@@moveString:
        CALL    Move

@@setString:
        MOV     EAX,EBX
        CALL    _LStrClr
        MOV     [EBX],EDI

@@exit:
        POP     EDI
        POP     ESI
        POP     EBX
end;
Да уж, другое измерение (согласитесь - читать легче, чем исходник топикстартера ). Свой вольный перевод сего (с небольшим урезанием "лишнего") в блок-схему я поместил во вложения, желательно, чтоб кто-нить более грамотный проверил на грубые ошибки.

С моей точки зрения, здесь довольно четко написано..., что, в случае со строкой, исходный массив КОПИРУЕТСЯ в новый блок памяти (в случае если есть "что" и "куда" копировать).

Но можно было не тратить время на изучение ассемблерной вставки, а просто выполнить копирование своими руками(чтоб точно знать)! Как это уже советовал сделать Скандербег, и как это делают адекватные программисты. (про оптимальность кода - ни слова! Я веду речь об надежности...)
Цитата:
а вот если сначала на один уменьшить, а потом обратно прибавить - нельзя быть таким увереным про восстановление данных.
Ёж и тот бы догадался, что память может кому-то другому срочно понадобится. Такие ситуации нужно устранять, а не обсуждать.

ЗЫ: ув. Андрей Куб, в сторону ваших замечаний, по поводу моих "где-то слышал" (где я такое говорил?):
1) Я это не "где-то слышал", я это читал в спец. литературе, а потом использовал на практике.
2) Я решаю задачи:
a) платно - ДА;
b) на энтузиазме - иногда ДА
с) на халяву - НЕТ!
По поводу вашего кода - вам уже сделали замечание об "элементарном уважении", а ваш оргумент по поводу того - полнейший бред.
И все, окончим на этом спор "ниачем".

ЗЗЫ: Если у вас динамический массив - это очередь из людей, а человек - это некая сущность с определенными статическим числом признаков, то непонятным становится как минимум то, что:
1) Почему это все хранится в памяти, а не на диске (предохранитель придут викрутят - и потеряете вы всю статистику за день! К тому же - память не резиновая, хоть и не в каменном веке живем! К тому же так легче - дин. массивы не пригодятся вообще!)
2) Почему "человек" - это массив, а не структура (очевидно, желаете запутать код и растолковать всем, что вы намного лучше все придумали - это я и называю "приступом гениальности")

Вот вам и решение , если я, конечно, не забыл про что-нибудь, чего вы не сказали :D

ИМХО тему пора закрывать - пусть учит матчасть на досуге...
Изображения
Тип файла: jpg block.jpg (28.8 Кб, 149 просмотров)
Copyright © qpokyc (qpy[the dog]bk.ru), 2008-2009 г.

Последний раз редактировалось qpokyc; 28.04.2009 в 07:56.
qpokyc вне форума
Закрытая тема


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не могу понять почему вылетает 3 процедурка, помогите Taisja Помощь студентам 2 04.06.2008 21:28
прога пишет ошибку при открытии файла (почему?) nicky777 Общие вопросы Delphi 2 14.03.2008 17:56
Есть готовая прога но запароленная, не могу запустить! Алёна Общие вопросы Delphi 4 29.10.2007 10:41