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

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

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

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

Сообщение zub » 12.02.2014 17:21:49

>>Но не лезу-ли я в "чужую" кучу?...
вполне может залезти, т.к. u непроинициализирован, также вконже нужно незабыть руками почистить хвосты, иначе один рефкаунт строки будет потерян для компилятора.
Должно быть както так:
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  u: Pointer;
begin
  u:=nil;//иначе следующая строка может вызвать AV изза возможного мусора в u

  String(u) := Edit2.Text;
  Edit1.Text:= IntToStr(Length(String(u)));

  String(u):=''; //иначе будет мемлик

end;
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

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

Сообщение VirtUX » 12.02.2014 17:26:02

ок. Но почему срабатывает без ошибок этот код?
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  u: Pointer;
begin

  u := nil;

  Integer(u) := 5789;
  Edit1.Text:= IntToStr(Integer(u));

end; 

Получается не нужно делать New(Integer(u));
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

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

Сообщение Sharfik » 12.02.2014 17:36:13

Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  u: Pointer;
begin

  String(u) := Edit2.Text; /// Тут написано Строка по адресу [b]u [/b]должна получить значение равное edit2.text, однако область памяти [b]u [/b]не назначена.
  Edit1.Text:= IntToStr(Length(String(u))); // если u=nil будет ошибка, если хоть чему то равен, даже случайно, то выдаст длину того куда нацелен.

end;


так понятней, но в зависимости от способа выдачи свойства Text будет по разному работать(напрямую или через функцию). Как и предыдущий вариант.
Код: Выделить всё
  u := addr(Edit2.Text)


С integer аналогично. В то ли в delphi, то ли еще где то видел галочку, чтобы компилятор переменным функций по умолчанию присваивал значение nil. Т.е. инициализировал. В нашем же случае они негде не инициализированы и рандомны.

Добавлено спустя 16 минут 35 секунд:
VirtUX писал(а):ок. Но почему срабатывает без ошибок этот код?
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  u: Pointer;
begin

  u := nil;

  Integer(u) := 5789;
  Edit1.Text:= IntToStr(Integer(u));

end; 

Получается не нужно делать New(Integer(u));

Pointer это числовое значение адреса переменной, т.е. это уже инициализированная ячейка памяти, которая размечена под хранение числа указывающего на другую область памяти. Мы банально меняем значение в переменной, и считываем его из одного и того же места.
Во всех примерах ошибка в том, что надо говорить программе, что работать нужно не с данными в переменной, а с данными по адресу, указанному в переменной.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 808
Зарегистрирован: 20.07.2013 01:04:30

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

Сообщение VirtUX » 12.02.2014 17:56:44

Sharfik писал(а):если u=nil будет ошибка

ничего подобного! При u=nil, Length(String(u)) - выдает размер равным нулю. А Integer(u), при том же u=nil - выдает тоже нуль :)
Я не могу понять - это глюк компилятора, или новая фича FPC 2.6.2?
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

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

Сообщение Sharfik » 12.02.2014 18:05:08

Я сам поспешил и потом и ниже сказал, что все примеры не правильные.
Код: Выделить всё
....

var
  Form1: TForm1;
  u: Pointer;
  qwe:string;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit1.Text:= string(u^); // Берем строку по адресу, в первый раз ошибка, во второй раз после нажатия кнопки два ошибки не будет
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  qwe := '333';
  u:=@qwe;
end;


Попробуй так. Сделал в Delphi если что :)
Последний раз редактировалось Sharfik 12.02.2014 18:07:10, всего редактировалось 1 раз.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 808
Зарегистрирован: 20.07.2013 01:04:30

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

Сообщение VirtUX » 12.02.2014 18:06:55

Для наглядности:
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
  u: Pointer;
  s: string;
begin

  u := nil;
  s := IntToStr(Integer(u));    // Здесь s = '0'
  Edit1.Text:= s;
  Integer(u) := 7878;
  s := IntToStr(Integer(u));    // Здесь s = '7878'
  Edit2.Text:= s;
  u := nil;
  s := IntToStr(Integer(u));    // Здесь снова s = '0'
  Edit3.Text:= s;

end; 


Добавлено спустя 2 минуты 43 секунды:
Sharfik писал(а):Edit1.Text:= string(u^);

Меня интересует Edit1.Text:= string(u);
Sharfik писал(а):qwe := '333';
u:=@qwe;

Это и так понятно, что правильно и по правилам :) Я тут про другое спрашиваю ;)
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

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

Сообщение Sharfik » 12.02.2014 18:10:46

VirtUX писал(а):Для наглядности:


Ты ему говоришь, что переменную pointer надо рассматривать как integer, т.е. кастануть и работать как с integer. Либо переключись на тип данных record, чтобы ошибки полезли либо пойми, что в примере используешь pointer как integer переменную.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 808
Зарегистрирован: 20.07.2013 01:04:30

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

Сообщение VirtUX » 12.02.2014 18:14:09

Sharfik писал(а):пойми, что в примере используешь pointer как integer переменную

))))))) Спасибо!!! Что-то торможу :)
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

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

Сообщение Sharfik » 12.02.2014 18:17:07

VirtUX писал(а):Меня интересует Edit1.Text:= string(u);

Мне кажется компилятору пофиг.

ему говорят работай с переменной как строкой, он и работает. Ему мофиг, что размер данных может по габаритам выйти за предел ячейки размечанной для pointer, если string окажется блольше
Edit1.Text:= string(u)
string(u):='4545';
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 808
Зарегистрирован: 20.07.2013 01:04:30

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

Сообщение zub » 12.02.2014 19:03:05

>>ничего подобного! При u=nil, Length(String(u)) - выдает размер равным нулю. А Integer(u), при том же u=nil - выдает тоже нуль
>>Я не могу понять - это глюк компилятора, или новая фича FPC 2.6.2?
Это особенность string`а, пустая строка представляется nil`ем в переменной, так было всегда

>>ок. Но почему срабатывает без ошибок этот код?
потому что в нем нету ниче криминального, другое дело если пытаться писать в область памяти куда указывает неинициализированный (или нулевой) указатель
Код: Выделить всё
  u := nil;
  Integer(u) := 5789;//ниче криминального, после этого указатель просто будет указывать на ячейку памяти 5789
  PInteger(u)^ := 1234;//так делать нельзя - пытаемся записать 1234 по адресу 5789, но хз что там лежит и разрешена ли туда запись. AV может и не быть сразу, поэтому подобные косяки очень трудно вылавливаются
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

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

Сообщение Дож » 12.02.2014 19:23:09

Чтобы код работал, нужно сделать проверку предположений о том, что при касте String уместится в Pointer, и что пустая строка действительно равна nil:
Код: Выделить всё
Assert(SizeOf(String) <= SizeOf(Pointer));
Assert(Pointer(String('')) = nil);


Иначе можно нарваться на интересные сюрпризы:
Код: Выделить всё
[doj@korica ~/temp]$ cat strsize.pas
begin
  Writeln(SizeOf(Pointer), ' ', SizeOf(String));
end.
[doj@korica ~/temp]$ fpc -Mdelphi strsize.pas && ./strsize
4 4
[doj@korica ~/temp]$ fpc strsize.pas && ./strsize
4 256


Код: Выделить всё
[doj@korica ~/temp]$ cat strnil.pas
begin
  Writeln(Pointer(String('')) = nil);
end.
[doj@korica ~/temp]$ fpc -Mdelphi strnil.pas && ./strnil
TRUE
[doj@korica ~/temp]$ fpc strnil.pas && ./strnil
strnil.pas(2,11) Error: Illegal type conversion: "ShortString" to "Pointer"
strnil.pas(4) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/local/bin/ppc386 returned an error exitcode
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

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

Сообщение zub » 12.02.2014 19:33:41

Компилятор это делает сам
>>strnil.pas(2,11) Error: Illegal type conversion: "ShortString" to "Pointer"
Конечно это не отменяет возможность кастануть так, что никто не догадается))
Всё вышесказанное мной не относится к ShortString
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

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

Сообщение Дож » 12.02.2014 21:27:43

Компилятор это делает сам
>>strnil.pas(2,11) Error: Illegal type conversion: "ShortString" to "Pointer"


Компилятор не сделал проверку на то, что '' = nil.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

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

Сообщение zub » 12.02.2014 21:52:07

>>Компилятор не сделал проверку на то, что '' = nil.
Вы серъезно? Какой в этом смысл?
Тогда уж и
Код: Выделить всё
Assert(Byte(false)=0);

Каждый раз проверять))
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

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

Сообщение Дож » 12.02.2014 22:14:47

Вы серъезно? Какой в этом смысл?


Да, я абсолютно серьёзен. Покажите в документации (или хотя бы в исходниках fpc), что String(nil) — это всегда пустая строка, а не что-то невалидное.

Каждый раз проверять))


Это, конечно, перебор, ибо это базовая вещь и задокументирована. Но польза от такой проверки тоже может быть
Код: Выделить всё
[doj@korica ~/temp]$ cat byte.pas
type
  TMySuperBool = (true, false);

begin
  Writeln(Byte(false));
end.
[doj@korica ~/temp]$ fpc byte.pas && ./byte
1
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Пред.След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 4

Рейтинг@Mail.ru