Работа со строками через адрес (PString, Pointer)

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Да, я абсолютно серьёзен. Покажите в документации (или хотя бы в исходниках fpc), что String(nil) — это всегда пустая строка, а не что-то невалидное.
http://www.freepascal.org/docs-html/ref ... 380003.2.6
If the string is empty (’’), then the internal pointer representation of the string pointer is Nil. If the string is not empty, then the pointer points to a structure in heap memory.

Исходников под рукой к сожалению нет, но там доказательств будет предостаточно

>>Это, конечно, перебор, ибо это базовая вещь и задокументирована. Но польза от такой проверки тоже может быть
Пользы от этого никакой нет, ибо это попытка выполнить работу компилятора и вынести ее в рантайм, хотя компилятор с ней прекрасно справится в compiletime
В данном примере TMySuperBool.false и boolean.false ничего общего не имеют, хоть и называются одинаково, компилятор не даст явно заменить одни другим. При желании програмист конечно может "кастануть" одно в другое, но это клиника... никакие проверки тут не помогут - лучше отрезать руки по самые колени))
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

zub писал(а):If the string is empty (’’), then the internal pointer representation of the string pointer is Nil. If the string is not empty, then the pointer points to a structure in heap memory.

Отсюда я могу сделать заключение, что...

Код: Выделить всё

...
var
u: Pointer = nil;
begin
String(u) := 'Any string';
...

... не будет вызывать исключений?

Добавлено спустя 7 минут 12 секунд:
проверил:

Код: Выделить всё

var
  u: Pointer;
  s: string;
begin

  String(u) := '';
  if Assigned(u) then s := 'true'
  else s := 'false';
  Edit1.Text:= s; // s = 'false'
  String(u) := 'wer';
  if Assigned(u) then s := 'true'
  else s := 'false';
  Edit2.Text:= s;  // s = 'true'

все верно -
VirtUX писал(а):не будет вызывать исключений
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Если чисто теоретически, то String(u) приводит указатель к типу String, но память под string не выделяет. Могу ошибаться, поэтому лучше всего спрашивать у разработчиков FreePascal.
Но если я прав, то просто используются ячейки памяти в куче без указания, что они заняты. Значит их кто-нибудь может перехватить на свои нужды.
Integer(u) - тот же принцип, но SizeOf(Pointer) = SizeOf(Integer), поэтому чужие ячейки памяти тут не используются.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

VirtUX писал(а):Отсюда я могу сделать заключение, что...Код: Выделить всё...varu: Pointer = nil;beginString(u) := 'Any string';...... не будет вызывать исключений?
проверил:

И в проверке забыл инициализировать u - так будет работать до поры пока в u не окажется какойнить мусор

Vadim писал(а):Если чисто теоретически, то String(u) приводит указатель к типу String, но память под string не выделяет.

выделяет - в этом случае все точно также какбудьто u объявлен стрингом, только без его автоматической инициализации\финализации, поэтому это нужно сделать руками
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

zub писал(а):И в проверке забыл инициализировать u

Так вот же:
VirtUX писал(а):String(u) := '';

Согласно сказанного:
zub писал(а):If the string is empty (’’), then the internal pointer representation of the string pointer is Nil.

и:
zub писал(а):Это особенность string`а, пустая строка представляется nil`ем в переменной, так было всегда


Добавлено спустя 57 секунд:
и при проверке (как видно из комментария) - это действительно - так
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Так вот же:
нет, это нето

u=nil;
просто запишет nil в указатель, а
String(u) := '';
перед записью проверит куда указывает u и если там не nil то попытается уменьшить рефкаунт и если надо финализировать строку, считая что u указывает на область памяти выделенную ранее "стринговыми" операциями. такчто именно на такой инициализации всё и вылетит, если u будет не инициализирован нормальным способом (например локальной переменной, в которой обычно лежит мусор)
перед кастованием указателя в стринг (не шортстринг) нужно обязательно позаботиться чтобы в нем был NIL или указатель на валидную строку
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

zub писал(а):>>Да, я абсолютно серьёзен. Покажите в документации (или хотя бы в исходниках fpc), что String(nil) — это всегда пустая строка, а не что-то невалидное.
http://www.freepascal.org/docs-html/ref ... 380003.2.6
If the string is empty (’’), then the internal pointer representation of the string pointer is Nil. If the string is not empty, then the pointer points to a structure in heap memory.

Исходников под рукой к сожалению нет, но там доказательств будет предостаточно


Верю, но документация лучше исходников — в исходниках пришлось бы проверять под разными платформами :)

С этого и надо было начинать, а то в теме постоянно идёт «проверка кодом, что это отработало и не упало».
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>а то в теме постоянно идёт «проверка кодом, что это отработало и не упало».
стринги (как и вся прямая работа с памятью) очень копризная штука, они могут падать только на "компе тёти Груни" или на "25ом" вызове этой безобидной процедуры или вообще в другом месте (когда какаято структура данных нужная сейчас в несвязанном напрямую с прошлым кодом месте была ранее "испорчена" неверным обращением со стрингами или памятью). Поэтому "проверка кодом" нужна очень серъезная, а не скомпилилось-неупало - значит всё ок.
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

zub, спасибо за подробные разъяснения!
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

стринги (как и вся прямая работа с памятью) очень копризная штука, они могут падать только на "компе тёти Груни" или на "25ом" вызове этой безобидной процедуры или вообще в другом месте (когда какаято структура данных нужная сейчас в несвязанном напрямую с прошлым кодом месте была ранее "испорчена" неверным обращением со стрингами или памятью). Поэтому "проверка кодом" нужна очень серъезная, а не скомпилилось-неупало - значит всё ок.


10 постами выше Вы сами высказывались против Assert'ов :)
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Я не против асертов, даже за)) просто в том примере они лишние - всё видно по соощениям компилятора.
Но от того молча ли упадет программа или предварительно поплачется в окно ассерта - пользователю легче не станет, а програмисту гораздо полезней лог и отладчик))
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

Я не против асертов, даже за)) просто в том примере они лишние - всё видно по соощениям компилятора.

Как раз таки для AnsiString тот ассерт сработал нормально (ошибка вываливалась для ShortString, и не на тему того, что nil <> '', а на тему того, что один тип не удалось сконвертировать). Ну, и тот мой ассерт проверяет не совсем то, что нужно, его нужно немного переписать, но в целом проверку nil = '' я не считаю такой уж плохой затеей, если относится с подозрением к строкам.

Ассерт сразу скажет в чём проблема, а AV может себя долго не проявлять.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Там была проверка того что задокументировано. Я не сторонник теории заговора, поэтому имхо это лишнее))
Проверка u на nil тоже выглядит странно - инициализировать забыли, а проверить не забыли - лучше стараться наоборот))
В общем случае в переменной лежит указатель на строку, а не nil и проверить его на валидность не получится. Такчто это не более чем проверка "а не забыли ли мы инициализировать переменную" или "не разучился ли компилятор сам инициализировать переменные" - в ходе работы программы и реальных багов наврятли поможет
По моему асерту место там, где несошлась контрольная сумма, не нашлось то что должно было найтись и т.п. случаях, но это имхо... а с тем что "лишних" проверок много не бывает я абсолютно согласен))
Ответить