Текущий архив: 2006.10.15;
Скачать: CL | DM;
ВнизПочему функция возвращает данные, которые ей недоступны Найти похожие ветки
← →
gosha67 (2006-09-26 16:49) [0]Здравствуйте уважаемые.
Я программист с некоторым опытом, но только сегодня я обнаружил сие недоразумение. Объясните мне пожалуйста почему в конечном итоге Data := "some text bla bla bla ...."? По идее она должна быть равно только "bla bla bla". Загадка какая-то.function GetSomeData: string;
var i : integer;
begin
for i := 1 to 20 do
begin
Result := Result + " bla bla bla";
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var Data : string;
begin
Data := "some text";
Data := GetSomeData;
ShowMessage(Data);
end;
← →
Игорь Шевченко © (2006-09-26 16:52) [1]
> По идее она должна быть равно только "bla bla bla".
Не должна.
> Загадка какая-то.
Чтобы не было загадки, надо переписать функцию:function GetSomeData: string;
var i : integer;
begin
Result := ""; for i := 1 to 20 do
begin
Result := Result + " bla bla bla";
end;
end;
← →
Джо © (2006-09-26 16:56) [2]> Я программист с некоторым опытом, но только сегодня я обнаружил
> сие недоразумение. Объясните мне пожалуйста почему в конечном
> итоге Data := "some text bla bla bla ...."? По идее она
> должна быть равно только "bla bla bla". Загадка какая-то.
Псевдо-переменная Result не инициализируется автоматически.
← →
Уч (2006-09-27 05:21) [3]Стало быть этим можно пользоваться вместо параметров при вызове функции? Будет ли результат гарантирован или компилятор может какой-нибудь изврат придумать?
← →
Пользователь (2006-09-27 09:49) [4]Стало быть этим можно пользоваться вместо параметров при вызове функции?
Чем вам не нравится использование параметров?
компилятор может какой-нибудь изврат придумать?
Если таким методом злоупотреблять, то, порой, компилятор начинает вписывать нецензурные слова. Правда, по-английски, но, все равно, перед пользователями неудобно...
Будет ли результат гарантирован?
Встреча с "восхищенными" пользователями вашей программы в темном корридоре без свидетелей - будет гарантирована точно. Но, при таком подходе к программированию, их (пользователей) будет немного. Так что, вероятно, вам удастся выжить.
← →
zamtmn © (2006-09-27 10:58) [5]>>Псевдо-переменная Result не инициализируется автоматически.
если cтринговая переменная не проинициализирована, то инициализировать ее нужно pointer(strvar):=nil, strvar:="" можно словить av
← →
Игорь Шевченко © (2006-09-27 11:18) [6]
> если cтринговая переменная не проинициализирована, то инициализировать
> ее нужно pointer(strvar):=nil, strvar:="" можно словить
> av
пример av в студию
← →
Johnmen © (2006-09-27 11:24) [7]
> Джо © (26.09.06 16:56) [2]
> Псевдо-переменная Result не инициализируется автоматически.
Строго говоря, инициализируется. Значением той переменной, которой присваивается возвращаемое ф-ей значение. По кр. мере так в D6.
Об этом говорит Sha ©.
← →
oxffff © (2006-09-27 11:25) [8]Сделай safecall. И будет тебе bla bla bla
function GetSomeData: string;safecall;
var i : integer;
begin
for i := 1 to 20 do
begin
Result := Result + " bla bla bla";
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var Data : string;
begin
Data := "some text";
Data := GetSomeData;
ShowMessage(Data);
end;
← →
Игорь Шевченко © (2006-09-27 11:29) [9]Johnmen © (27.09.06 11:24) [7]
Вообще-то об этом говорит и Borland :)
← →
Johnmen © (2006-09-27 11:31) [10]
> Игорь Шевченко © (27.09.06 11:29) [9]
> Johnmen © (27.09.06 11:24) [7] Вообще-то об этом говорит
> и Borland :)
Возможно. Только я Борланда не читаю...:))
← →
oxffff © (2006-09-27 11:32) [11]Вам поможет safecall, который очищает result параметр перед вызовом.
Cмотрите oxffff © (27.09.06 11:25) [8]
← →
oxffff © (2006-09-27 11:38) [12]А что касаемо сабжа. Автору лучше посмотреть на asm и станет все понятно
register
leax eax,[data]
call GetSomeData
safecall
leax eax,[data]
call LstrClr
push eax
call GetSomeData
....
← →
oxffff © (2006-09-27 11:40) [13]прошу прощения за опечатку естественно LEA, а не leax
← →
zamtmn © (2006-09-27 11:54) [14]>>пример av в студию
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
var strvar:string;
i:Cardinal;
begin
for i:=1 to 100000 do
//будем перебирать варианты неинициализированной strvar
//хотя ошибку словим уже на первом:)
begin
pointer(strvar):=pointer(i);
strvar:="";
end;
end.
← →
ЮЮ © (2006-09-27 11:58) [15]//будем перебирать варианты неинициализированной strvar
> pointer(strvar):=pointer(i);
Ничего себе "переборчик" :)
← →
zamtmn © (2006-09-27 12:04) [16]а что такого? эмуляция неинициализированности:)
как сказано в [7] result:string автоматически инициализируемая переменная, иначе result:="" не прокатило бы
← →
Игорь Шевченко © (2006-09-27 12:06) [17]zamtmn © (27.09.06 11:54) [14]
> for i:=1 to 100000 do
> //будем перебирать варианты неинициализированной strvar
> //хотя ошибку словим уже на первом:)
> begin
> pointer(strvar):=pointer(i);
> strvar:="";
> end;
Я не вижу неинициализированной strvar, первой же строкой из цикла ты ее "инициализируешь" в недопустимое значение.
Советую посмотреть CPU Window и понять, что так делать нельзя.
← →
Игорь Шевченко © (2006-09-27 12:08) [18]zamtmn © (27.09.06 12:04) [16]
> как сказано в [7] result:string автоматически инициализируемая
> переменная, иначе result:="" не прокатило бы
Ты прочитай [7] два раза вдумчиво. Пойми, где используется слово Result и почему оно инициализируется.
← →
zamtmn © (2006-09-27 12:15) [19]>>Я не вижу неинициализированной strvar, первой же строкой из цикла ты ее "инициализируешь" в недопустимое значение.
Советую посмотреть CPU Window и понять, что так делать нельзя.
а ты увидь, если бы компилятор не позаботился о result, то result вполне бы указывал на недопустимое значение.
в делфи любой стринг локальный, глобальный инициализируется автоматически, неинициализированный стринг можно получить только создав его динамически.
>>Советую посмотреть CPU Window и понять, что так делать нельзя.
я какраз туда регулярно заглядываю, это вообщето был пример неинициализированного стринга
← →
oxffff © (2006-09-27 12:23) [20]В [7] написано некорре
ктно
Строго говоря, инициализируется. Значением той переменной, которой присваивается возвращаемое ф-ей значение. По кр. мере так в D6.
Об этом говорит Sha ©.
Оно ничем не инициализируется. В данном случае возвращаемое значение это синоним Data.
← →
Игорь Шевченко © (2006-09-27 12:29) [21]zamtmn © (27.09.06 12:15) [19]
> если бы компилятор не позаботился о result, то result вполне
> бы указывал на недопустимое значение
В твоем примере слова Result нету, это раз.
> глобальный инициализируется автоматически
В твоем примере strvar объявлен, как глобальный, значит, уже проинициализирован, это два.
Ты не используй сослагательного наклонения, ты пример приведи без извратов, чтобы подтвердить свою точку зрения из поста [5]
> если cтринговая переменная не проинициализирована, то инициализировать
> ее нужно pointer(strvar):=nil, strvar:="" можно словить
> av
← →
oxffff © (2006-09-27 12:34) [22]Когда объявляется
a:string;
begin
....
то происходит
Push 0, а не sub esp,4.
Поэтому переменная A уже инициализированна
← →
zamtmn © (2006-09-27 12:38) [23]в [5] нет "слова Result" там говорится прои инициализацию. var:="" ты присвоишь значение, но не инициализируешь стринг
← →
Игорь Шевченко © (2006-09-27 12:45) [24]zamtmn © (27.09.06 12:38) [23]
Код будет или будут длинные рассуждения ?
> var:="" ты присвоишь значение, но не инициализируешь стринг
Внимательно читать раздел Declaring and initializing strings в родной справке.
← →
oxffff © (2006-09-27 12:49) [25]Тогда мы объявляем
var a:string;
begin
Он инициализирован. Cм. oxffff © (27.09.06 12:34) [22]
если делаем так
var a:pstring;
begin
new(a);
Он тоже инициализирован.
А вот если делаем так
var a:string;
p:pointer;
begin
pointer(a):=p;
тогда естественно DWORD(a):=0;
← →
zamtmn © (2006-09-27 12:57) [26]Игорь Шевченко © (27.09.06 12:45) [24]
>>Код будет или будут длинные рассуждения ?
код с неинициализированным стрингом был.
>>Внимательно читать раздел Declaring and initializing strings в родной справке.
внимательно читать [19]
← →
Игорь Шевченко © (2006-09-27 13:02) [27]zamtmn © (27.09.06 12:57) [26]
> код с неинициализированным стрингом был.
Не было. Был код с глобальной переменной типа string, которая и без того инициализирована. А твои действия с pointer, это, извини, твои фантазии. Нафантазировать можно много чего, но причем здесь реальные ситуации, я не понимаю.
← →
zamtmn © (2006-09-27 13:11) [28]>>Не было. Был код с глобальной переменной типа string, которая и без того
>>инициализирована.
после действий с поинтером, она таковой быть перестала.
var ps:pstring;
begin
getmem(ps,sizeof(string));
//вот тебе неинициализированная ps^;
{pointer(ps^):=nil;}
ps^:="";
//а вот тут частенько будут av
//а если раскоментировать строку выше то их небудет.
..................
хочу заметить, я не говорил что в [0] нужно делать pointer(result):=nil, я говорил о неинициализированных переменных
← →
clickmaker © (2006-09-27 13:19) [29]
> если cтринговая переменная не проинициализирована, то инициализировать
> ее нужно pointer(strvar):=nil, strvar:="" можно словить
> av
чё за бред?
← →
Игорь Шевченко © (2006-09-27 13:23) [30]zamtmn © (27.09.06 13:11) [28]
Ты примеры из пальца высасываешь ? В твоем примере AV будет всегда, потому что разыменование неинициализированного указателя гарантировано вызовет AV.
Ты получил указатель, ссылащийся неизвестно куда, но в строчке
> ps^:="";
ты почему-то считаешь, то он указывает на string.
Так нельзя делать.
← →
Johnmen © (2006-09-27 13:26) [31]
> zamtmn © (27.09.06 13:11) [28]
А где здесь переменная типа string?
← →
Palladin © (2006-09-27 13:29) [32]
> zamtmn © (27.09.06 13:11) [28]
а причем здесь pstring если речь в ветке идет о простом string? да и на кой нужен getmem если делается проще: new(ps)
← →
zamtmn © (2006-09-27 13:36) [33]>>Ты получил указатель, ссылащийся неизвестно куда, но в строчке
здрасте... он указывает на стринг который компилятором не проинициализирован.
← →
Palladin © (2006-09-27 13:50) [34]не нужно очевидностей не имеющих отношения к теме, все что ты сказал относится к любому указателю...
> он указывает на стринг
раз пошла речь о банальнастях то он указывает не на стринг, а на область памяти, которую компилятор будет считать переменной типа стринг при выделении памяти, а заполнить ты ее можешь чем угодно, хоть ссылкой на объект
← →
zamtmn © (2006-09-27 13:52) [35]var ps:pbyte;
begin
getmem(ps,sizeof(byte));
ps^:=255;
..................
тут тоже неизвестно куда?
← →
clickmaker © (2006-09-27 13:52) [36]
> здрасте... он указывает на стринг который компилятором не
> проинициализирован
матерь божья... сколько можно пургу гнать?
← →
Palladin © (2006-09-27 13:56) [37]
> clickmaker © (27.09.06 13:52) [36]
да он кому-то что-то доказывает... не понятно, только, что именно :)
← →
zamtmn © (2006-09-27 13:58) [38]>>раз пошла речь о банальнастях то он указывает не на стринг, а на
>>область памяти, которую компилятор
а что тогда есть стринг:)?
да меня под чютким подначиванием Игорь Шевченко © вильнуло в сторону от сабжа. я уж и не помню кто сказал что result не проинициализированна. она проинициализирована, только содержит неопределенное значение
← →
Palladin © (2006-09-27 14:02) [39]
> zamtmn © [38]
Result не является указателем на стринг, равно как и b:byte, тоже не является указателем, это раз, два: стринг (в отличии от указателя на стринг) есть указатель на область памяти содержащую набор символов...
и Result действительно не проинициализирован, но на AV присвоением ему значения ты никоим образом нарваться не можешь
← →
zamtmn © (2006-09-27 14:09) [40]>>и Result действительно не проинициализирован
дубль 2
ps=pstring;
getmem(ps,sizeof(string));
ps^ - это стринг и не проинициализированый
а result из [0] проинициализированый, что прекрасно видно в debug cpu window
Страницы: 1 2 3 вся ветка
Текущий архив: 2006.10.15;
Скачать: CL | DM;
Память: 0.56 MB
Время: 0.048 c