Форум: "Основная";
Текущий архив: 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.047 c