Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Кто внятно пояснит в чём проблема ?


Страницы:   1 2 3

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
Код корректный ?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо