![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Кто внятно пояснит в чём проблема ?
Kozhanov © (2002-05-31 14:01:00)type
PString = ^String;
procedure TForm1.Button1Click(Sender: TObject);
var
A : array[1..8] of Byte;
begin
FillChar(A, SizeOf(A), 0);
PString(@A[1])^ := "hello, buddy !";
PString(@A[5])^ := "good-bye, buddy !"; //здесь происходит
//крушение если заремить первую строчку ?!!!!!!!!
ShowMessage(PString(@A[1])^);
ShowMessage(PString(@A[5])^);
end;
SPeller (2002-05-31 15:25:00) [21]Да, похоже что никакого выхода за пределы массива тут нет. На своей 6-й сделал так:
procedure TForm1.Button1Click(Sender: TObject);
var a:array[1..8]of byte;
begin
//fillchar(a,8,0);
pstring(@a[1])^:="hello, buddy !";
label1.Caption:=pstring(@a[1])^;
//a[4]:=100;
label2.Caption:=pstring(@a[1])^;
end;
Оказывается, что в первых четырёх байтах массива хранится указатель на нормальную строку. Поэтому присвоение другого значения первым четырём байтам приведёт к ошибке при считыванииlabel2.Caption:=pstring(@a[1])^;. Остальные байты можно изменять как угодно и на результат это никак не скажется. И FillChar тут ни причём.
Внук (2002-05-31 15:25:00) [22]>>Игорь Шевченко © (31.05.02 15:12)
Ну естественно, не будет, вылазим за пределы отведенной памяти, но не через обращение A[i], а через запись строки, это же разные вещи
Kozhanov (2002-05-31 15:23:00) [23]>Внук
"неужели Delphi должна заботиться об автоматическом выделении памяти и сборке мусора ???"
Твой вопрос закономерен и меня он тоже волнует.
Но самое странное что вся моя байда работает (!!!).
Если бы Делфи вываливалать и говорила что ты мол дурак, это
было бы понятно, а то...В общем не понятно, как же на самом деле
всё это работает и почему ?
Игорь Шевченко (2002-05-31 15:23:00) [24]Внук © (31.05.02 15:17)
Все, теперь мы друг друга поняли :-)
Выражение PString(@A[1])^ заставляет компилятор трактовать выражение как String, если указатель равен нулю, то _LstrAsg прекрасно работает. В противном случае, он начинает интерпретировать тот мусор, который в стеке, как строку со всеми вытекающими.
Надо PString(@A[1]) := @строки, тогда уж.
Код у автора кривой вдвойне :-)))
С уважением,
Внук (2002-05-31 15:17:00) [25]>>Игорь Шевченко © (31.05.02 15:02)
Извиняюсь, не заметил, что это тот же самый код :) У меня он тоже работает, но я продолжаю утвержать, что это некорректно.
А вот при закомментаренной FillChar и ShowMessage(PString(@A[1])^) (как Вы советовали) вылетает ошибка. Как же это объяснить?
По-моему, все прозрачно. Если я захочу произвольный участок памяти трактовать как AnsiString, неужели Delphi должна заботиться об автоматическом выделении памяти и сборке мусора ???
Kozhanov (2002-05-31 15:13:00) [26]Господа, посмотрите ещё раз вопрос !
Я же просил пояснить (кто сможет) почему код не работает
если заремить FillChar(A, SizeOf(A), 0), а вы начинаете говорить
что код вообще идиотский и всё такое. Это первое...Второе :
если код неправильный, то покажите мне ситуацию при которой он
рухнет, буду очень признателен за науку...
Игорь Шевченко (2002-05-31 15:12:00) [27]Только сейчас поглядел, что в моем примере с record первое поле - лишнее.
Надо:
type
TmyCoolRecord = packed record
B : PString;
C : PString;
end;
Заело, думал, что массив с нуля начинается.
Внук © (31.05.02 15:05)
>Ну а почему нельзя вылезти за пределы массива? Можно... До поры, до времени
Откомпилируйте код с Range Check - ошибок не будет :-)
Там нет выхода за пределы массива. :-))
MBo (2002-05-31 15:08:00) [28]так тоже работает ;)
begin
s:=caption;
ptr:=pointer(s);
это же просто пояснение к AnsiString
Kozhanov (2002-05-31 15:08:00) [29]>Внук
До какой поры и до какого времени ?
Внук (2002-05-31 15:05:00) [30]"И ещё почему если код не корректный, то он РАБОТАЕТ ?"
Ну а почему нельзя вылезти за пределы массива? Можно... До поры, до времени.
Kozhanov (2002-05-31 15:02:00) [31]>MBo
setlength(s,$10000); - а почему бы вообще всю память у машины не
отобрать ?
И ещё почему если код не корректный, то он РАБОТАЕТ ?
Игорь Шевченко (2002-05-31 15:02:00) [32]Внук © (31.05.02 14:58)
Я привел пример кода автора, работающего в моей среде Delphi.
D5/WinNT.
Он работает. Другое дело, что это кривой способ :-)
С уважением,
Внук (2002-05-31 15:00:00) [33]MBo © (31.05.02 14:56)
>>setlength(s,$10000);
Именно об этом я и говорю :)
Внук (2002-05-31 14:58:00) [34]>>Игорь Шевченко © (31.05.02 14:50)
Про то, что не будет работать, я имел в виду код автора. Вы в чем не согласны с Внук © (31.05.02 14:43) ?
MBo (2002-05-31 14:56:00) [35]>Код корректный ?
нет, вот корректный
procedure TForm1.Button1Click(Sender: TObject);
var s:string;
ptr:pointer;
begin
setlength(s,$10000);
ptr:=pointer(s);//или PChar
label1.caption:=IntToHex(Cardinal(ptr),8);
ptr:=@s[1];
label2.caption:=IntToHex(Cardinal(ptr),8);
end;
Внук (2002-05-31 14:56:00) [36]>>Kozhanov © (31.05.02 14:47)
"Delphi сама выделяет память под String..."
Угу, жедезно. Только покажите мне в Вашей программе переменную типа String
Kozhanov (2002-05-31 14:53:00) [37]>SPeller
"и последние шесть символов выходят за пределы массива"
Тогда почему же ShowMessage(PString(@A[1])^) и ShowMessage(PString(@A[5])^) всё правильно выводят ?
Игорь Шевченко (2002-05-31 14:52:00) [38]В дополнение:
Крах происходит потому, что "заремив" первую строчку все равно остается вызов ShowMessage(PString(@A[1])^);.
Ее тоже надо "заремить"
Игорь Шевченко (2002-05-31 14:50:00) [39]Внук © (31.05.02 14:43)
procedure TForm1.Button4Click(Sender: TObject);
var
A : array[1..8] of Byte;
begin
FillChar(A, SizeOf(A), 0);
PString(@A[1])^ := "hello, buddy !";
PString(@A[5])^ := "good-bye, buddy !";
ShowMessage(PString(@A[1])^);
ShowMessage(PString(@A[5])^);
end;
Все прекрасно работает :-)
Kozhanov © (31.05.02 14:38)
Это - изврат :-)
Не изврат:
type
TmyCoolRecord = packed record
A : Byte;
B : PString;
C : PString;
end;
Kozhanov (2002-05-31 14:49:00) [40]>MBo
Код корректный ?