Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.12.12;
Скачать: CL | DM;

Вниз

Dynamic arrays и TStream   Найти похожие ветки 

 
Grim   (2004-11-28 01:00) [0]

Доброго всем времени суток!
У меня возник такой вопрос.
Есть таблица с данными (T), записанная в dynamic array of TActorInfo,
где TActorInfo - рекорд из различного типа данных (Bool, Float, Int).

Таблица пересылается через методы idUDPServer.SendBuffer;
UDPServer.SendBuffer(IPAdress, Port, T[0], SizeOf(TActorInfo)*Length(T));

Теперь на другом конце Я должен получить точно такой же массив Т:

UDPServerUDPRead(Sender: TObject; AData: TStream;ABinding: TIdSocketHandle);
begin
 SetLength(T, 2); //ye допустим я знаю сколько записей там
 Adata.Read(T, SizeOf(TActorInfo)*2);  
end;

После этого обращение к Т вызывает ошибку "память там-то не может быть
считана" (обычная).
Вопрос: что я делаю не так или как это сделать иначе (UDP протокол необходим)?


 
Verg ©   (2004-11-28 13:13) [1]


> Adata.Read(T[0], SizeOf(TActorInfo)*2);  


 
Суслик ©   (2004-11-28 13:20) [2]

если не ошибаюсь, то еще так можно

Adata.Read(pointer(T)^, SizeOf(TActorInfo)*2);

Опять же, если не ошибаюсь, то так более правильно для пустого массива...


 
jack128 ©   (2004-11-28 14:45) [3]

Суслик ©   (28.11.04 13:20) [2]
Кстати, некоторое время назад я отказался от подобного подхода, потому что приходится менять код если изменяешь декларацию со статического массива на динамический и наоборот. Тоже(даже в большей степени) для длинных и коротких строк.


 
Суслик ©   (2004-11-28 14:50) [4]


>  [3] jack128 ©   (28.11.04 14:45)

мне как-то не часто приходится менять декларацию указанным способом.
Зато контролировать, чтобы при обращении чере [0] был первый элемент мне доставляет большие неудобства.


 
GuAV ©   (2004-11-28 16:13) [5]

Суслик ©   (28.11.04 14:50) [4]

Hа самом деле контролировать не нужно. Если pointer(T) = nil, то и T[0] равен nil. Более того сгенерированный компилятором код будет одинаковым.

procedure Test(var X);
begin
 ShowMessageFmt("%X",[Integer(@X)]);
end;

procedure TForm1.FormCreate(Sender: TObject);
var X: array of Integer;
begin
 Test(X[0]);  // 0
 Test(Pointer(X)^); // 0
end;


 
Суслик ©   (2004-11-28 16:16) [6]


>  [5] GuAV ©   (28.11.04 16:13)


>  T[0] равен nil

ну это уже compiler magic...
В дельфи и не такое бывает :)))


 
Суслик ©   (2004-11-28 16:18) [7]


> [5] GuAV ©   (28.11.04 16:13)

Честно говоря я не помню, где в документации декларировано, что T[0] = nil если T = nil. Наверное, раз вы говорите, это так. Но мне как-то кажется это не очень хорошо выглядит. Поэтому если я пользуюсь T[0], то всегда проверяю. Спасибо за информацию, теперь буду знать (когда проверю, конечно :)))


 
Игорь Шевченко ©   (2004-11-28 17:40) [8]


> Если pointer(T) = nil, то и T[0] равен nil.


Все правильно. Перадача var-параметра происходит по ссылке (в данном адрес T соответствует адресу T[0]), от этого и сгенерированный код одинаковый.


> ну это уже compiler magic...


Да нет, никаких magic-ов.

Кстати, поделитесь, кто как выходит из ситуации, когда функция требует var-параметра (например, Integer или DWORD), а хочется передать nil ?

Почему возник вопрос - часть функций в Windows.pas описана принимающими var-параметры, хотя по описанию функции (в MSDN) она вполне может принимать nil.


 
Verg ©   (2004-11-28 17:48) [9]


> [8] Игорь Шевченко ©   (28.11.04 17:40)


> Кстати, поделитесь, кто как выходит из ситуации, когда функция
> требует var-параметра (например, Integer или DWORD), а хочется
> передать nil ?


nil^


 
Суслик ©   (2004-11-28 17:55) [10]

Появилось время проверить
Такой код дает range check error... при всключенном {$R+}

var
  i: array of integer;
  d: integer;
begin
  move(i[0], d, 4);
end;


Так, что правда никокого compiler magic - это просто не фига не работает :)))


 
Verg ©   (2004-11-28 17:58) [11]


> Такой код дает range check error... при всключенном {$R+}
>
> var
>   i: array of integer;
>   d: integer;
> begin
>   move(i[0], d, 4);
> end;


Ну да, теперь осталось проверить ;) что произойдет, если заметить i[0] на pointer(i)^.


 
Суслик ©   (2004-11-28 18:01) [12]


>  [11] Verg ©   (28.11.04 17:58)

Я не очень понимаю о чем ты?
Если о av, то данный код был примером того, что i[0] дает range check error в том случае, гда массив пустой. И МОЕ утвержение опровергнутое в [5] о том, что в случае [0] надо проверять наличие элементов имеет смысл.


 
Суслик ©   (2004-11-28 18:02) [13]


> [11] Verg ©   (28.11.04 17:58)

ты только посмотри последовательсность и смысл постов, прежде чем отвечать :)))))


 
Verg ©   (2004-11-28 18:03) [14]


> [2] Суслик ©   (28.11.04 13:20)
> если не ошибаюсь, то еще так можно
>
> Adata.Read(pointer(T)^, SizeOf(TActorInfo)*2);
>
> Опять же, если не ошибаюсь, то так более правильно для пустого
> массива...


В любом случае необходимо проверять, что массив не пуст.


 
Суслик ©   (2004-11-28 18:04) [15]


>  [14] Verg ©   (28.11.04 18:03)


> В любом случае необходимо проверять, что массив не пуст.

в данном конкретном случае да, но если было так:

Adata.Read(pointer(T)^, SizeOf(TActorInfo)*length(T));

то не надо


 
Verg ©   (2004-11-28 18:10) [16]


> [15] Суслик ©   (28.11.04 18:04)
>
> >  [14] Verg ©   (28.11.04 18:03)
>
>
> > В любом случае необходимо проверять, что массив не пуст.
>
> в данном конкретном случае да, но если было так:
>
> Adata.Read(pointer(T)^, SizeOf(TActorInfo)*length(T));
>
> то не надо


Спор беспредметен, т.к. ты расчитываешь на то, что виртуальный метод Read у потока проверит на <>0 Count, который ему передадут. Т.о. собственно к динамич. массивам это не имеет ровно никакого отношения.
В общем слуаче как раз проверять на неноль длину массива.


 
Verg ©   (2004-11-28 18:18) [17]

Мало того, что ты предпологаешь, что переменная типа дин. массив - это указатель на данные (Почему бы?) хранящиеся в этом массиве, так и

Do not apply the dereference operator (^) to a dynamic-array variable.... (С) Delphi Help.


 
Суслик ©   (2004-11-28 18:22) [18]


>  [17] Verg ©   (28.11.04 18:18)

открою тебе секрет, я не пользуюсь динамическими массивами :)))
т.о. я ничего не продполагаю
Все мое участие в данном топике сводится к тому, что я сказал, что есть еще путь. Сомневаюсь, что толькоя по нему хожу


 
Суслик ©   (2004-11-28 18:24) [19]


> Do not apply the dereference operator (^) to a dynamic-array variable

уверен, что ты это вырвал из контекста.

В свое время когда дельфи стало возможно откзаться от ^ в отношении указателей, в описании наверняка была такая же фраза. Однако, сомневаюсь, что она что-то значит больше, чем дословный перевод.


 
Verg ©   (2004-11-28 18:34) [20]

Конечно вырвал.

Dynamic-array variables are implicitly pointers and are managed by the same reference-counting technique used for long strings. To deallocate a dynamic array, assign nil to a variable that references the array or pass the variable to Finalize; either of these methods disposes of the array, provided there are no other references to it. Dynamic arrays of length 0 have the value nil. Do not apply the dereference operator (^) to a dynamic-array variable or pass it to the New or Dispose procedure.

Но ты-то так и не указал - на чем, собственно, основано твое предположение, что pointer(DynArray) указывает на область памяти, где хранятся данные массива, а не, например, управляющая им структура, где среди прочих элементов есть и указатель на память с данными массива.


 
Игорь Шевченко ©   (2004-11-28 18:34) [21]

Verg ©   (28.11.04 17:48) [9]

Спасибо :) Все гениальное просто :)


 
Суслик ©   (2004-11-28 18:37) [22]


> Но ты-то так и не указал - на чем, собственно, основано
> твое предположение,

Ты шататный хелп дельфи читал?

Может я вчера родился, но описание -4 или -8 в отношении указателя всегда расценивалось, как вмещение относительно указателя

A dynamic-array variable occupies four bytes of memory which contain a pointer to the dynamically allocated array. When the variable is empty (uninitialized) or holds a zero-length array, the pointer is nil and no dynamic memory is associated with the variable. For a nonempty array, the variable points to a dynamically allocated block of memory that contains the array in addition to a 32-bit length indicator and a 32-bit reference count. The table below shows the layout of a dynamic-array memory block.

Offset Contents
–8 32-bit reference-count
–4 32-bit length indicator (number of elements)
0..Length * (size of element) – 1 array elements

(выдержка их хелпа).

Ладно, хватит, писюлями меряться.
Сам же сказал разговор беспредметный.


 
Verg ©   (2004-11-28 18:40) [23]


> Ладно, хватит, писюлями меряться.


Писюлями? :)))
Есть тема, вопрос и я на нее ответил. Все остальное - это у кого чего болит, тот о том  и говорит..


 
Суслик ©   (2004-11-28 18:42) [24]


>  [23] Verg ©   (28.11.04 18:40)


> Есть тема, вопрос и я на нее ответил

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


 
Verg ©   (2004-11-28 18:47) [25]


> [24] Суслик ©   (28.11.04 18:42)


МЧ. Вы и на самом дело очень болезненно воприниаете.

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


 
Суслик ©   (2004-11-28 18:49) [26]


> Verg ©   (28.11.04 18:47) [25]

Ну ладно, ладно - давайте жить дружно.
Собственно давайте подведем итог:

Чем по вашему обращение вида pointer(dynarray)^ хуже dynarray[0]?

Коротко и ясно. Думаю, что все уже сказано - но думаю нас могут читать начинающие, надо для них постараться :))


 
Verg ©   (2004-11-28 18:54) [27]


> [26] Суслик ©   (28.11.04 18:49)


Я просто скажу свое мнение, просто еще раз

pointer(dynarray)^  - это притянутое за уши преобразование типов, пользуясь знаниями текущей реализации этого типа данных в текущем релизе компилера и runtimelib

dynarray[0] - это чистокровный 0-вой элемент массива, безо всяких "если".

Все.


 
Суслик ©   (2004-11-28 18:58) [28]


>  [27] Verg ©   (28.11.04 18:54)


> dynarray[0] - это чистокровный 0-вой элемент массива, безо
> всяких "если".

Вот позвольте, придраться к слову "чистокровный".
В рамках дельфи и того compiler magic, который он сует в код, говорить о чискоровности не приходится. Уж извините.
Как нет гарантии, что pointer(d) будет в будущем показывать на начало данных, так нет гарантии, что @(d[0]) также показывает на начало данных.
Например, это может быть адрес функции доступа к элементу массива. Почему нет? Да шансе изменеия такого рода сущесвенно меньше, чем подход к pointer(d), но они есть.

Если же говорить о сухой практике, то и тот и другой подход будут работать. Дельфи не сможет отказаться от такой реализации массивов. Т.к. я часто видел в чужих компонентах использование pointer...


 
Verg ©   (2004-11-28 19:41) [29]


> так нет гарантии, что @(d[0]) также показывает на начало
> данных.


Зачем же искажать мои слова? Точнее приписывать мне того, чего я не говорил?

d[0] - это нулевой элемент массива. Будешь оспаривать?

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


 
Суслик ©   (2004-11-29 11:06) [30]


> d[0] - это нулевой элемент массива. Будешь оспаривать?

это значение нулевого элемента массива...

И вообще, не обижайся, если есть на что... Правды в виртуальном общении не найдешь :)

Но дело в том, что pointer(str)^ или pointer(dynarray)^ есть используемый многими путь обращения к данным... При том путь допустимый соглавно текущей документации к языку разработки delphi (выдержку из справки я приводил, она находтися в разделе memory managment). Если смотреть в будущее, то там все равно будут такие подходы, которые не позволят пользовать ни тем, ни другим методом доступа к данным.



Страницы: 1 вся ветка

Текущий архив: 2004.12.12;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.043 c
1-1101878308
dolphin
2004-12-01 08:18
2004.12.12
record с неизвестным количеством переменных


3-1100453708
Недалекий
2004-11-14 20:35
2004.12.12
Delphi - IBX - Insert


1-1101297114
col-isaev
2004-11-24 14:51
2004.12.12
параметры функций в ДЛЛ


14-1101192856
passlight
2004-11-23 09:54
2004.12.12
Сбойная память : способы использования


1-1101608873
noob
2004-11-28 05:27
2004.12.12
Event