![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Корректное создание массива из пользовательских структур. [D7]
justnick © (2006-05-03 19:53:00)Привет всем. У меня тут проблемка с массивом структур. Вот выдержки из кода:
type
TMyRecord = record
var1, var2: Double;
// и т.д. всего на 272 байта
end;
TForm1 = class(TForm)
public
MRA: array of TMyRecord;
IA: array of Integer;
procedure MRACalc(var MR: TMyRecord);
end;
implementation
procedure TForm1.Button1Click(Sender: TObject);
begin
// создаю MRA, пробовал через setLength и GetMem
SetLength(MRA, N);
// GetMem(MRA, SizeOf(TMyRecord) * N);
// создаю и инициализирую массив IA
SetLength(IA, M);
for i := 0 to M - 1 do IA[i] := i;
// на этом работа с IA в данной процедуре заканчивается
// далее идет довольно большой блок операций с MRA и вызовом проедуры MRACalc
end;
так вот. по завершению этого события массив IA деформируется. у него изменяется общее количество элементов, и сами значения элементов тоже меняются, вплоть до чисел с плавающей точкой (по крайней мере так дебаггер показывает). Но если создавать IA раньше чем MRA то все работает нормально. Отсюда сделал вывод, что не корректно создаю MRA (хотя операции с любым из его элементов работают без сбоев). Подскажите плз где лажанулся, а то не охота потенциальную багу оставлять.
Sapersky (2006-05-04 16:15:00) [1]> 1. массив одномерный потому что он мне физически нужен одномерный,
Физически он всегда будет одномерным
Наверное имелась в виду нефрагментированность, т.е. чтобы "одним куском".
А двумерный динамическиймассив (array of array of TMyRecord), это, вроде как, массив одномерных динамических массивов (указателей), со всеми вытекающими.
TUser (2006-05-04 14:39:00) [2]> 1. массив одномерный потому что он мне физически нужен одномерный,
Физически он всегда будет одномерным. В 2-мерном D возьмет насебя всю эту индексную арифметику.
> он должен быть глобальный поскольку нужен в других процедурах
Да ради бога.
> если бы были выходы за границы массива MRA то тогда бы ругалось инвалид пойнтер операшинами
не факт.
justnick (2006-05-04 12:49:00) [3]мля.... я неисправимо туп... дейтсвительно вылезает за рамки..... только вот оно обычно еррор раньше выкидывало :-) звыняйте за флуд
ПС. мне нужно к массиву обращаться как MRA[i] (через один индекс а не через два, а два индекса нужны только чтобы координаты узлов посчитать) массив по условиям задачи одномерный при любом раскладе
Sapersky (2006-05-04 12:44:00) [4]Физически одномерный двумерный массив:
PMyRecArr = ^TMyRecArr;
TMyRecArr = array [0..0] of TMyRecord;
PMyRecArr2D =^TMyRecArr2D;
TMyRecArr2D = array [0..0] of PMyRecArr;
Var Arr : PMyRecArr2D;
begin
GetMem(Arr, Width * Height * SizeOf(TMyRecord));
for y := 0 to Height - 1 do begin
for x := 0 to Width - 1 do begin
Arr[y,x] := ... // индексы пишутся в обратном порядке
Ещё одна особенность - т.к. это не динамический массив, а типизированный указатель - посмотреть его содержимое отладчиком нельзя.
ЮЮ (2006-05-04 12:38:00) [5]>5. еще заметил если в коде MRACalc не вызывать,
Естественно, если память не портить, то сама она портиться не станет. И, наоборот, если она "портится", то во всем виноват твой код.
ЮЮ (2006-05-04 12:30:00) [6]Какой "математический" смысл имеет MRA[i * CCount + j + 1]
на последней итерации циклов, кроме как попытки вылезть за пределы массива? :)
justnick (2006-05-04 12:26:00) [7]5. еще заметил если в коде MRACalc не вызывать, или вызывать но с пустым телом то все ОК. все начинается когда повялется математика в MRACalc типа
with MR do
ai := X2 * Y3 - X3 * Y2;
justnick (2006-05-04 12:23:00) [8]4. оценщиков кода просьба не беспокоиться.... оптимизацией буду заниматься когда все и так заработает, а так мне виднее математический смысл, проще отлаживать (если кто с конечными элементами сталкивался поймет)
ЮЮ (2006-05-04 12:21:00) [9][i, j] = i * CCount + j
Поэтому конструкцию MRA[i * CCount + j + 1 лучше не использовать. В этом случае лучше индекс j правильго менять. Да и вычислить i * CCount + j один раз в начале внутреннего цикла - и символов меньше и смысл очевиднее
justnick (2006-05-04 12:20:00) [10]3. если бы были выходы за границы массива MRA то тогда бы ругалось инвалид пойнтер операшинами.... все циклы выполняются, т.к. RCount и CCount всегда больше нуля, а RCount * CCount = N ... с Range Checking ща погляжу
justnick (2006-05-04 12:16:00) [11]2.все массивы глобальные... плюс отключал оптимайзер..... ну а стал я заниматься этим только после того как стало глючить обращение к IA (он тоже глобальный) в другой процедуре
justnick (2006-05-04 12:14:00) [12]доброе утро.... спасибо за понимание.... ща постраюсь разрулить некоторые вопросы
1. массив одномерный потому что он мне физически нужен одномерный, и он должен быть глобальный поскольку нужен в других процедурах, но при этом он описыват плоскость разбитую на конечные элементы, которе в свою очередь характеризуются количеством строк и столбцов
evvcom (2006-05-04 09:36:00) [13]
> MRACalc вынеси из объекта - на 1 параметр сократишЪ стек:
> быстрее будет
Self передается здесь через eax, а не через стек.
Loginov Dmitry (2006-05-04 08:55:00) [14]
> Slym © (04.05.06 05:09) [10]
> Slym © (04.05.06 05:12) [11]
Какие классы? Какой стек? Какие указатели?
Зачем вводить человека в заблуждение?
TUser (2006-05-04 08:50:00) [15]Предположу, что все нумеруется с нуля, в RCount и CCount - число стро и столбцов в некоторой таблице. Тогда у тебя написано слудующее
for i := 0 to RCount - 1 do begin
for j := 0 to CCount - 1 do begin
if j + 1 < CCount then begin
{j < CCount - 1
тут используются
MRA[i * CCount + j + 1]
MRA[i * CCount + j]}
end else begin
{j = CCount - 1
тут используются
MRA[i * CCount + j + 1] // при i = RCount выходим за границу массива
MRA[(i-1) * CCount + j + 1]}
...
Slym (2006-05-04 05:12:00) [16]justnick (03.05.06 19:53)
Подскажите плз где лажанулся, а то не охота потенциальную багу оставлять.
В итоге ты лажанулся с дебагером: нефиг смотреть по недействительному указателю
Slym (2006-05-04 05:09:00) [17]1. Нечитабелен и тормознут
ты скока раз написал строку:
i * CCount + j + 1 и (i-1) * CCount + j + 1 ?
каждый раз индекс вычисляется и смещение в блоке памяти...
2. Двухмерная работа с одномерным массивом? Делай двухмерный массив! Или масссив of массив
MRACalc вынеси из объекта - на 1 параметр сократишЪ стек: быстрее будет
justnick (03.05.06 19:53)
так вот. по завершению этого события массив IA деформируется. у него изменяется общее количество элементов, и сами значения элементов тоже меняются, вплоть до чисел с плавающей точкой
ясен пень... указатель на массив уже не действителен а ты его дебагером... а тот блок памяти уже кто-то занял вот ты и видишь мусор через призму своего TMyRecord...
Зачем временные переменные описывать в классе? объявляй, создавай и оперируй ими в процедуре.
Loginov Dmitry (2006-05-03 23:20:00) [18]Код абсолютно нечитабелен. Оценил бы на 2 с двумя минусами.
По сабжу: почему бы не сделать массив двухмерным - бесконечный расчет смещений может вас сильно запутать.
evvcom (2006-05-03 22:52:00) [19]
> for i := 0 to RCount - 1 do begin
> for j := 0 to CCount - 1 do begin
> if j + 1 < CCount then begin
> if MRA[i * CCount + j].UP then begin
Скорее всего происходит выход за границы массива MRA. Если бы указал, чему равны RCount, CCount и N, то может и получил бы уже тык пальцем. И еще, галка Range Checking стоит?
Мефисто (2006-05-03 21:20:00) [20]Вах!... Черт ногу сломит в таком коде =)
Еще покажи MRACalc ();
>> for i := 0 to RCount - 1 do begin
>> for j := 0 to CCount - 1 do begin
Всегда ли 100% вероятностью выполняются данные условия т.е. циклы?