Какие строки лучше использовать
От: ThreeD  
Дата: 07.08.06 10:07
Оценка:
Добрый день.
Возник такой вопрос, два разработчика пишут клиент-серверное приложение, один пишет сервер — другой клиент. Сервер пишется на C++ а клиент на паскале (делфи). Возник спор — какой формат строк использовать или что лучше в данном приложении. дело в том что в паскале строки записываются в пакет в формате [длина строки] + [строка без 0 символа], а в си строки в формате [строка + 0 символ]. И вот при согласовании формата пакетов возник такой спор — каждый настаивает что нужно использовать именно "его" формат.
Паскалист привел такие доводы:

По 2-м причинам. 1-е скорость. Копровать Сишные строки из одного буффера в другой медленней чем паскалевскую строку из одного буффера в другой и диже копирование паскалевской строки из одного буффера в сишный вариант в другой буффер (конвертация на лету). Объясняю:
Принцип копирования строки типа Си:
Пусть даны 2-е строки s1 и s2 в s1 записанно "Привет#0" (7 байт) Размер s2 пока не известен (считаем что динамически выделяем память). Тогда надо посчитать длинну s1: проверить каждый байт на #0 и если нет — увеличить счётчик. Как только посчитали — сделать getmem на s2 (или malloc) и скопировать от адреса строки до адреса строки + её длинна -1
Принцип копирования строки типа Паскаль:
Читаем 1-й байт строки (если строка максимум 255) — это размер строки. делаем getmem (malloc) на размер+1 и копируем туда от начала строки до начала + длинна строки (-1 нету).
Принцип копирования из строки типа паскаль в строку типа Си:
Читаем 1-й байт. Делаем getmem(malloc) копируем от начала +1 до начала +длинна и в начало +длинна +1 ставим #0

Скорость очевидна. Теперь рассмотрим если буффер для s2 уже задан (в строке типа СИ):
начинается самое интересное. Пусть под s2 уже выделенно 100 байт, тогда копирование проводится следующем образом: копируется каждый байт из s1 в s2 со смещением до тех пор, пока не будет #0 оно копируется и процесс завершается.
Здаесь есть одно бальшое НО: Есл s1 больше 100 байт то мы выйдем за приделы буффера и будем копировать уже поверх программы (так как в Си данные можно объявить где хочешь)... По идеи получем GPF, но на самом деле не всегда... Если после 100 значения будет уже скомпилированный код, то файкически он будет выполняться. Это и есть атака на переолнения буффера. Это вторая причина. Из метода копирования ясно, что при работе с паскалевскими строками такой атаки быть не может просто! Конечно есть способ и в Си, позволяющий обойти эту ататку щас я его расскажу:
При копировании из s1 в s2 ведётся счётчик и если он =100 то в s2 записывается #0 и копирование обрывается. Или идет увеличение буффера.
ЗЫ: основная проблема Си строк(да и вообще с любыми строками) это то что всегда прежде чем работать с ними нужна их длинна, а она и Си строках очень долго определяется.

По поводу Паскалевских строк. Ситы утверждают что можно "насрать" в 1-й байт. Да можно, но если его уменьшить — данные просто потеряются, есл увеличить — это будет часть строки, НО ОНО НИКОГДА НЕ БУДЕТ ВЫПОЛНЯТЬСЯ!!!!

В приведённых выше примерах я, кажется, разобрал все способы и при том защищенное копирование строк в Си делается способом занимающем больше времени (этот алгоритм оптимизирован), а если хранить длинну строки в Си... то смысл? тогда это будет паскалевская строка с #0 сзади.

Если непонятно — могу привести код на ассемблере для пояснения.

Из всего вышесказанного: паскалевские строки и быстрее и надежнее. А выигрыш по памяти при работе с короткими строками (до 255) вообще никакой.


в свою очередь другой ссылается, что ему не удобны такие строки, потомучто у себя он их будет конвертировать в сишный формат, там использовать, потом обратно перед отправкой пакета переконвертировать и терять скорость работы. + поддержка длинных строк более 255 символов вызывает большое сомнение у него (2 байта потребует для указания длины).
Подскажите, что лучше всетаки использовать сишные строки или паскалевские?
Re: Какие строки лучше использовать
От: Lloyd Россия  
Дата: 07.08.06 10:15
Оценка: +1
Здравствуйте, ThreeD, Вы писали:

TD>Возник такой вопрос, два разработчика пишут клиент-серверное приложение, один пишет сервер — другой клиент. Сервер пишется на C++ а клиент на паскале (делфи). Возник спор — какой формат строк использовать или что лучше в данном приложении. дело в том что в паскале строки записываются в пакет в формате [длина строки] + [строка без 0 символа], а в си строки в формате [строка + 0 символ]. И вот при согласовании формата пакетов возник такой спор — каждый настаивает что нужно использовать именно "его" формат.

TD>Паскалист привел такие доводы:

Прошу прощения, но кажется, то что говорит паскались уже несколько лет как неверно: начиная с какой-то версии строки в дельфи — по умолчанию null-terminated.
Re: Какие строки лучше использовать
От: CreatorCray  
Дата: 07.08.06 10:34
Оценка:
Здравствуйте, ThreeD, Вы писали:

TD>По 2-м причинам. 1-е скорость. Копровать Сишные строки из одного буффера в другой медленней чем паскалевскую строку из одного буффера в другой и диже копирование паскалевской строки из одного буффера в сишный вариант в другой буффер (конвертация на лету).

Экономим на спичках? Ничто не мешает использовать std::string у которого размер хранится в строке и он safe в отношении криворукости программера при копировании строк.

TD>По поводу Паскалевских строк.

хранить размер в первом байте — ИМХО через задницу. Если хочется хранить — то уж лучше класс а-ля std::string.

TD>Из всего вышесказанного: паскалевские строки и быстрее и надежнее.

false

TD>Подскажите, что лучше всетаки использовать сишные строки или паскалевские?

Для интерконнекта ИМХО формат пакета должен задавать сервер. И уж клиенты должны подстраиваться.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[2]: Какие строки лучше использовать
От: Cyberax Марс  
Дата: 07.08.06 10:46
Оценка:
CreatorCray wrote:
> TD>По 2-м причинам. 1-е скорость. Копровать Сишные строки из одного
> буффера в другой медленней чем паскалевскую строку из одного буффера в
> другой и диже копирование паскалевской строки из одного буффера в сишный
> вариант в другой буффер (конвертация на лету).
> Экономим на спичках? Ничто не мешает использовать std::string у которого
> размер хранится в строке и он safe в отношении криворукости программера
> при копировании строк.
Кстати, и при формировании строки std::string будет быстрее, так как
позволяет зарезервировать место заранее.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[2]: Какие строки лучше использовать
От: ThreeD  
Дата: 07.08.06 10:48
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Прошу прощения, но кажется, то что говорит паскались уже несколько лет как неверно: начиная с какой-то версии строки в дельфи — по умолчанию null-terminated.


Вот чел который пишет клиент (на паскале) с пеной у рта доказывает что так, паскаль умеет вроде в сишный формат, но он этого не будет, потомучто якобы строки в паскалевском формате копируются быстрее и безопаснее.
Поэтому клиент должен принимать пакеты где строки в этом формате и никак иначе. Только сервер с ними работать не будет, а будет всеравно конвертить из одного в другое а потом обратно. ИМХО это не верно, но чел уперся. Вот поэтому хотим услышать ваше мнение, чтобы разрешить конфликт этот.
Re[3]: Какие строки лучше использовать
От: Warstone  
Дата: 07.08.06 10:50
Оценка: +1
Здравствуйте, ThreeD, Вы писали:


TD>Вот чел который пишет клиент (на паскале) с пеной у рта доказывает что так, паскаль умеет вроде в сишный формат, но он этого не будет, потомучто якобы строки в паскалевском формате копируются быстрее и безопаснее.

TD>Поэтому клиент должен принимать пакеты где строки в этом формате и никак иначе. Только сервер с ними работать не будет, а будет всеравно конвертить из одного в другое а потом обратно. ИМХО это не верно, но чел уперся. Вот поэтому хотим услышать ваше мнение, чтобы разрешить конфликт этот.

Ну не перевирай... Я пытаюсь объяснить что в пакете передичи надо держать длинну у строки а не по #0 её обрывать.
Re[3]: Какие строки лучше использовать
От: Lloyd Россия  
Дата: 07.08.06 10:51
Оценка:
Здравствуйте, ThreeD, Вы писали:

TD>Вот чел который пишет клиент (на паскале) с пеной у рта доказывает что так, паскаль умеет вроде в сишный формат, но он этого не будет, потомучто якобы строки в паскалевском формате копируются быстрее и безопаснее.

TD>Поэтому клиент должен принимать пакеты где строки в этом формате и никак иначе. Только сервер с ними работать не будет, а будет всеравно конвертить из одного в другое а потом обратно. ИМХО это не верно, но чел уперся. Вот поэтому хотим услышать ваше мнение, чтобы разрешить конфликт этот.

Пусть просто произведет замеры. Но не в синтетическом тесте, а хотя бы чуть-чуть приближенном к реальности. Тогда он увидит, что принцыпиальной разницы в производительности не будет.
Re[2]: Какие строки лучше использовать
От: Warstone  
Дата: 07.08.06 10:53
Оценка:
Здравствуйте, CreatorCray, Вы писали:
CC>Экономим на спичках? Ничто не мешает использовать std::string у которого размер хранится в строке и он safe в отношении криворукости программера при копировании строк.

Вот и я про то-же. А теперь давайте подумаем чем отличается этот тип строки от паскалевской? Ага... #0 сзади (причем наверно, так как я туда не смотрел) И что мешает ему в пакете сначала прочитать длинну строки, а потом брать строчку (а ведь имеено из-за этого весь сыр-бор)
Re[4]: Какие строки лучше использовать
От: CreatorCray  
Дата: 07.08.06 11:20
Оценка:
Здравствуйте, Warstone, Вы писали:

W>Ну не перевирай... Я пытаюсь объяснить что в пакете передичи надо держать длинну у строки а не по #0 её обрывать.

Зависит от требований к размеру пакета. Если не критично +2 байта на строку для ее размера (1 байт ИМХО слишком большая экономия, все же 255 символов для строки это не так и много, + заклад на будущее потенциальное расширение формата) то вполне стоит хранить в пакете длинну строки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re: Какие строки лучше использовать
От: ArhAngelVezel Россия  
Дата: 07.08.06 11:33
Оценка: -2 :)
Здравствуйте, ThreeD, Вы писали:

TD>Из всего вышесказанного: паскалевские строки .. быстрее ...


нифифа:


for j:=0 to 1000000 do
 begin
  s:="";
  for i:=0 to 200 do
    begin
     s := s + "1";
    end;
 end;



В паскале: пишиться байт, получается первый байт, инкриментируется, пишиться первый байт.
В С: пишиться байт, пишиться #0...

Есть разница?
Re[3]: Какие строки лучше использовать
От: CreatorCray  
Дата: 07.08.06 11:37
Оценка:
Здравствуйте, Warstone, Вы писали:

W>Здравствуйте, CreatorCray, Вы писали:

CC>>Экономим на спичках? Ничто не мешает использовать std::string у которого размер хранится в строке и он safe в отношении криворукости программера при копировании строк.

W>Вот и я про то-же. А теперь давайте подумаем чем отличается этот тип строки от паскалевской? Ага... #0 сзади (причем наверно, так как я туда не смотрел) И что мешает ему в пакете сначала прочитать длинну строки, а потом брать строчку (а ведь имеено из-за этого весь сыр-бор)


Все равно это не чистый паскалевский формат записи будет.
Предлагаю что нить типа:

WORD stringSize — 2 байта на размер строки включая \0 в конце
ASCIIZ string — zero-tеrminated строка
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[5]: Какие строки лучше использовать
От: ThreeD  
Дата: 07.08.06 11:43
Оценка:
Вопрос видимо сводится к тому в каком формате передавать строки в пакете: указывать ли перед строкой ее длину, а саму строку без 0 в конце, или передавать стандартные строки с 0 в конце. Со стороны сервера без разницы как придет строка (просто будет несколько лишних операций по считыванию этой длины а потом самой строки или за 1 проход в случае стандартной строки). При запись ответа от сервера — опять определение длины строки, потом запись в пакет самой строки за вычетом 0. А сами строки на сервере будут использоваться через std::string. Сервер расчитывается на подключении нескольких тысяч клиентов одновременно. Вот и хочется занть как лучше передавать строки в пакете — в паскалевском или в сишном формате, как быстрее будет и удобнее (сервер на СИ)
Re[6]: Какие строки лучше использовать
От: CreatorCray  
Дата: 07.08.06 11:58
Оценка:
Здравствуйте, ThreeD, Вы писали:

TD>Вопрос видимо сводится к тому в каком формате передавать строки в пакете: указывать ли перед строкой ее длину, а саму строку без 0 в конце, или передавать стандартные строки с 0 в конце. Со стороны сервера без разницы как придет строка (просто будет несколько лишних операций по считыванию этой длины а потом самой строки или за 1 проход в случае стандартной строки). При запись ответа от сервера — опять определение длины строки, потом запись в пакет самой строки за вычетом 0. А сами строки на сервере будут использоваться через std::string. Сервер расчитывается на подключении нескольких тысяч клиентов одновременно. Вот и хочется занть как лучше передавать строки в пакете — в паскалевском или в сишном формате, как быстрее будет и удобнее (сервер на СИ)

Лучше в паскалевском [размер][строка]
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re: Какие строки лучше использовать
От: Hobot Bobot США  
Дата: 07.08.06 12:11
Оценка: +9
Что-то я не вижу, как формат строки в пакете данных зависит от языка программирования.
Я всегда для передачи через TCP использовал формат с размером строки в начале. Хоть в C, хоть в C#, хоть в Delphi. Просто потому, что такие строки удобнее принимать (читаем размер, потом строку):

recv(sock, &size, 2, 0);
recv(sock, &buffer, size, 0);
buffer[size] = 0;
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
Re: Какие строки лучше использовать
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 07.08.06 12:11
Оценка: +2
Здравствуйте, ThreeD, Вы писали:

Так в Дельфи, если мне не изменяет память, этот вопрос был с первой или второй версии решен. Со смещением -4 хранится длина, сама строка заканчивается 0.
... << RSDN@Home 1.2.0 alpha rev. 642>>
AVK Blog
Re: Какие строки лучше использовать
От: _doctor Финляндия http://agilesoftwaredevelopment.com
Дата: 07.08.06 19:36
Оценка:
Здравствуйте, ThreeD, Вы писали:

TD>Добрый день.

TD>Возник такой вопрос, два разработчика пишут клиент-серверное приложение, один пишет сервер — другой клиент. Сервер пишется на C++ а клиент на паскале (делфи). Возник спор — какой формат строк использовать или что лучше в данном приложении. д

Лучше не путать формат пакета данных с форматами строк клиента и сервера
Передавайте строки как вам угодно и конвертируйте на обеих сторона если надо. Если хотите выбрать формат сетевых пакетов, то надо спрашивать не программеров клиента и сервера, а проектировщика протокола. Обычно по сети удобнее передавать данные с заранее указанной длиной.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Chief Software Engineer,
Scrum Master, Symbian
Re[4]: Какие строки лучше использовать
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.08.06 22:32
Оценка: +1 :)))
Здравствуйте, CreatorCray, Вы писали:
CC>Все равно это не чистый паскалевский формат записи будет.
CC>Предлагаю что нить типа:

CC>WORD stringSize — 2 байта на размер строки включая \0 в конце

CC>ASCIIZ string — zero-tеrminated строка
Ну надо же. Еще немного, и вы изобретете борландовский AnsiString.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Какие строки лучше использовать
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.08.06 22:32
Оценка: 3 (1) +5 :))) :))) :)))
Здравствуйте, ThreeD, Вы писали:

TD>Добрый день.

TD>Возник такой вопрос, два разработчика пишут клиент-серверное приложение, один пишет сервер — другой клиент. Сервер пишется на C++ а клиент на паскале (делфи). Возник спор — какой формат строк использовать или что лучше в данном приложении. дело в том что в паскале строки записываются в пакет в формате [длина строки] + [строка без 0 символа], а в си строки в формате [строка + 0 символ]. И вот при согласовании формата пакетов возник такой спор — каждый настаивает что нужно использовать именно "его" формат.
TD>Паскалист привел такие доводы:
Паскалиста немедленно уволить за некомпетентность. Сишника отправить на курсы повышения квалификации.
Причины:
1. Паскаль, который использовал первый байт строки для хранения длины, умер более 10 лет назад. Все 32-разрядные Delphi, естественно, хранят длину в 32-разрядном интегере.
2. Delphi, естественно, заканчивает все свои строки нулем. Для того, чтобы легче было интероперировать с C и С++.
3. Сишника нужно срочно обучить C++ и заставить забыть ASCIIZ как страшный сон. Потому как даже если лично он умеет бороться с ликами и buffer overrun-ами, то никто не сможет обеспечивать это при внесении изменений в его код. В плюсах уже давно можно использовать стандартные безопасные строковые классы, а уж единожды написать конвертер для такой строки в какой бы то ни было формат пакета для программиста проблемы представлять не должно.

З.Ы. Надо полагать, братанам попала 273 часть вторая, и они пытались совершить побег? Не могу придумать другого места, где они могли провести 15 лет в столь хорошей изоляции от внешнего мира.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Какие строки лучше использовать
От: vdimas Россия  
Дата: 08.08.06 03:05
Оценка:
Здравствуйте, ThreeD, Вы писали:

BSTR поддерживается и там и там. Полностью безопасно, если в C++ использовать готовые классы для работы с BSTR.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Какие строки лучше использовать
От: Left2 Украина  
Дата: 08.08.06 07:41
Оценка:
S>З.Ы. Надо полагать, братанам попала 273 часть вторая, и они пытались совершить побег? Не могу придумать другого места, где они могли провести 15 лет в столь хорошей изоляции от внешнего мира.

Статья 273. Создание, использование и распространение вредоносных программ для ЭВМ

1. Создание программ для ЭВМ или внесение изменений в существующие программы, заведомо приводящих к несанкционированному уничтожению, блокированию, модификации либо копированию информации, нарушению работы ЭВМ, системы ЭВМ или их сети, а равно использование либо распространение таких программ или машинных носителей с такими программами —

наказываются лишением свободы на срок до трех лет со штрафом в размере до двухсот тысяч рублей или в размере заработной платы или иного дохода осужденного за период до восемнадцати месяцев.

2. Те же деяния, повлекшие по неосторожности тяжкие последствия, —

наказываются лишением свободы на срок от трех до семи лет.


Нда... Разве что если они взломали тюремный компьютер и добавили себе срок...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.