Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.12.12;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.033 c
1-1101876703
zunder
2004-12-01 07:51
2004.12.12
plug-in


1-1101455243
msm
2004-11-26 10:47
2004.12.12
Запись текста в файл


1-1101736159
hgd
2004-11-29 16:49
2004.12.12
Как открыть папку


1-1101826657
Павел
2004-11-30 17:57
2004.12.12
Таймер в многопоточном приложение


8-1095138488
resha
2004-09-14 09:08
2004.12.12
Обработка звука!!!





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский