Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.10.15;
Скачать: [xml.tar.bz2];

Вниз

Почему функция возвращает данные, которые ей недоступны   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.056 c
3-1155246216
Oxot_nik
2006-08-11 01:43
2006.10.15
Как создать дерево таблиц в Базе данных?


2-1159358066
Fostr
2006-09-27 15:54
2006.10.15
Передать данные из одной формы в другою


15-1158838499
StriderMan
2006-09-21 15:34
2006.10.15
Софт для управления проектами


3-1155644577
RomanH
2006-08-15 16:22
2006.10.15
Начальное значение генератора


15-1158908682
Opilki_Inside
2006-09-22 11:04
2006.10.15
Парсер аргументов командной строки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский